Compare commits

..

7 Commits

Author SHA1 Message Date
38c1a981e8 Clock element as a standalone component
- Was intended to replace clock indicator;
- WIP!
2019-06-25 10:10:58 -07:00
50944cfed0 Status bar migration to top of layout, WIP
- Added tracking style to indicator-template;
- Moved click action to button in label of globalClearIndicator;
- Removed unnecessary markup in Indicators.vue;
- Commented out __head collapse button for now in Layout.vue;
2019-06-07 19:04:30 -07:00
27b236ffe4 Status bar migration to top of layout, WIP
- Refine styles and markup for Indicators;
- Better separation of styles for clickable and non-clickable
Indicators;
2019-06-07 18:30:08 -07:00
b7e75bcc22 Status bar migration to top of layout, WIP
- Refine and remove legacy styles for Indicators;
- Significant cleanup in Indicator markup;
- Remove unnecessary wrapper component StatusBar.vue;
- Move collapse-button styles to a more general location in _controls
.scss;
- New hasMenu mixin to allow easier application of disclosure control
styling;
2019-06-07 16:07:50 -07:00
210a23dfe2 styling 2019-06-06 15:29:19 -07:00
84bfb9e8cc global clear works on plots 2019-06-06 15:06:03 -07:00
fd749253d9 first proto of global clear, working on tables 2019-06-06 14:38:41 -07:00
587 changed files with 28247 additions and 33321 deletions

View File

@ -2,7 +2,7 @@ version: 2
jobs: jobs:
build: build:
docker: docker:
- image: circleci/node:13-browsers - image: circleci/node:8-browsers
environment: environment:
CHROME_BIN: "/usr/bin/google-chrome" CHROME_BIN: "/usr/bin/google-chrome"
steps: steps:
@ -11,17 +11,17 @@ jobs:
name: Update npm name: Update npm
command: 'sudo npm install -g npm@latest' command: 'sudo npm install -g npm@latest'
- restore_cache: - restore_cache:
key: dependency-cache-13-{{ checksum "package.json" }} key: dependency-cache-{{ checksum "package.json" }}
- run: - run:
name: Installing dependencies (npm install) name: Installing dependencies (npm install)
command: npm install command: npm install
- save_cache: - save_cache:
key: dependency-cache-13-{{ checksum "package.json" }} key: dependency-cache-{{ checksum "package.json" }}
paths: paths:
- node_modules - node_modules
- run: - run:
name: npm run test:coverage name: npm run test
command: npm run test:coverage command: npm run test
- run: - run:
name: npm run lint name: npm run lint
command: npm run lint command: npm run lint

View File

@ -1,4 +1,3 @@
const LEGACY_FILES = ["platform/**", "example/**"];
module.exports = { module.exports = {
"env": { "env": {
"browser": true, "browser": true,
@ -6,17 +5,9 @@ module.exports = {
"jasmine": true, "jasmine": true,
"amd": true "amd": true
}, },
"globals": { "extends": "eslint:recommended",
"_": "readonly"
},
"extends": [
"eslint:recommended",
"plugin:vue/recommended",
"plugin:you-dont-need-lodash-underscore/compatible"
],
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "babel-eslint", "parser": "babel-eslint",
"parserOptions": {
"allowImportExportEverywhere": true, "allowImportExportEverywhere": true,
"ecmaVersion": 2015, "ecmaVersion": 2015,
"ecmaFeatures": { "ecmaFeatures": {
@ -24,9 +15,6 @@ module.exports = {
} }
}, },
"rules": { "rules": {
"you-dont-need-lodash-underscore/omit": "off",
"you-dont-need-lodash-underscore/throttle": "off",
"you-dont-need-lodash-underscore/flatten": "off",
"no-bitwise": "error", "no-bitwise": "error",
"curly": "error", "curly": "error",
"eqeqeq": "error", "eqeqeq": "error",
@ -70,88 +58,7 @@ module.exports = {
} }
], ],
"dot-notation": "error", "dot-notation": "error",
"indent": ["error", 4], "indent": ["error", 4]
// https://eslint.org/docs/rules/no-case-declarations
"no-case-declarations": "error",
// https://eslint.org/docs/rules/max-classes-per-file
"max-classes-per-file": ["error", 1],
// https://eslint.org/docs/rules/no-eq-null
"no-eq-null": "error",
// https://eslint.org/docs/rules/no-eval
"no-eval": "error",
// https://eslint.org/docs/rules/no-floating-decimal
"no-floating-decimal": "error",
// https://eslint.org/docs/rules/no-implicit-globals
"no-implicit-globals": "error",
// https://eslint.org/docs/rules/no-implied-eval
"no-implied-eval": "error",
// https://eslint.org/docs/rules/no-lone-blocks
"no-lone-blocks": "error",
// https://eslint.org/docs/rules/no-loop-func
"no-loop-func": "error",
// https://eslint.org/docs/rules/no-new-func
"no-new-func": "error",
// https://eslint.org/docs/rules/no-new-wrappers
"no-new-wrappers": "error",
// https://eslint.org/docs/rules/no-octal-escape
"no-octal-escape": "error",
// https://eslint.org/docs/rules/no-proto
"no-proto": "error",
// https://eslint.org/docs/rules/no-return-await
"no-return-await": "error",
// https://eslint.org/docs/rules/no-script-url
"no-script-url": "error",
// https://eslint.org/docs/rules/no-self-compare
"no-self-compare": "error",
// https://eslint.org/docs/rules/no-sequences
"no-sequences": "error",
// https://eslint.org/docs/rules/no-unmodified-loop-condition
"no-unmodified-loop-condition": "error",
// https://eslint.org/docs/rules/no-useless-call
"no-useless-call": "error",
// https://eslint.org/docs/rules/wrap-iife
"wrap-iife": "error",
// https://eslint.org/docs/rules/no-nested-ternary
"no-nested-ternary": "error",
// https://eslint.org/docs/rules/switch-colon-spacing
"switch-colon-spacing": "error",
// https://eslint.org/docs/rules/no-useless-computed-key
"no-useless-computed-key": "error",
// https://eslint.org/docs/rules/rest-spread-spacing
"rest-spread-spacing": ["error"],
"vue/html-indent": [
"error",
4,
{
"attribute": 1,
"baseIndent": 0,
"closeBracket": 0,
"alignAttributesVertically": true,
"ignores": []
}
],
"vue/html-self-closing": ["error",
{
"html": {
"void": "never",
"normal": "never",
"component": "always"
},
"svg": "always",
"math": "always"
}
],
"vue/max-attributes-per-line": ["error", {
"singleline": 1,
"multiline": {
"max": 1,
"allowFirstLine": true
}
}],
"vue/multiline-html-element-content-newline": "off",
"vue/singleline-html-element-content-newline": "off"
}, },
"overrides": [ "overrides": [
{ {
@ -167,13 +74,6 @@ module.exports = {
} }
] ]
} }
}, {
"files": LEGACY_FILES,
"rules": {
// https://eslint.org/docs/rules/no-nested-ternary
"no-nested-ternary": "off",
"no-var": "off"
}
} }
] ]
}; };

80
API.md
View File

@ -52,6 +52,7 @@
- [The URL Status Indicator](#the-url-status-indicator) - [The URL Status Indicator](#the-url-status-indicator)
- [Creating a Simple Indicator](#creating-a-simple-indicator) - [Creating a Simple Indicator](#creating-a-simple-indicator)
- [Custom Indicators](#custom-indicators) - [Custom Indicators](#custom-indicators)
- [Included Plugins](#included-plugins)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@ -108,13 +109,15 @@ script loaders are also supported.
<html> <html>
<head> <head>
<title>Open MCT</title> <title>Open MCT</title>
<script src="dist/openmct.js"></script> <script src="openmct.js"></script>
</head> </head>
<body> <body>
<script> <script>
openmct.setAssetPath('openmct/dist');
openmct.install(openmct.plugins.LocalStorage()); openmct.install(openmct.plugins.LocalStorage());
openmct.install(openmct.plugins.MyItems()); openmct.install(openmct.plugins.MyItems());
openmct.install(openmct.plugins.UTCTimeSystem()); openmct.install(openmct.plugins.UTCTimeSystem());
openmct.install(openmct.plugins.Espresso());
openmct.start(); openmct.start();
</script> </script>
</body> </body>
@ -125,6 +128,9 @@ The Open MCT library included above requires certain assets such as html
templates, images, and css. If you installed Open MCT from GitHub as described templates, images, and css. If you installed Open MCT from GitHub as described
in the section on [Building from Source](#building-from-source) then these in the section on [Building from Source](#building-from-source) then these
assets will have been downloaded along with the Open MCT javascript library. assets will have been downloaded along with the Open MCT javascript library.
You can specify the location of these assets by calling `openmct.setAssetPath()`.
Typically this will be the same location as the `openmct.js` library is
included from.
There are some plugins bundled with the application that provide UI, There are some plugins bundled with the application that provide UI,
persistence, and other default configuration which are necessary to be able to persistence, and other default configuration which are necessary to be able to
@ -231,7 +237,7 @@ attributes
of this object. This is used for specifying an icon to appear next to each of this object. This is used for specifying an icon to appear next to each
object of this type. object of this type.
The [Open MCT Tutorials](https://github.com/nasa/openmct-tutorial) provide a The [Open MCT Tutorials](https://github.com/openmct/openmct-tutorial) provide a
step-by-step examples of writing code for Open MCT that includes a [section on step-by-step examples of writing code for Open MCT that includes a [section on
defining a new object type](https://github.com/nasa/openmct-tutorial#step-3---providing-objects). defining a new object type](https://github.com/nasa/openmct-tutorial#step-3---providing-objects).
@ -423,12 +429,12 @@ attribute | type | flags | notes
###### Value Hints ###### Value Hints
Each telemetry value description has an object defining hints. Keys in this this object represent the hint itself, and the value represents the weight of that hint. A lower weight means the hint has a higher priority. For example, multiple values could be hinted for use as the y-axis of a plot (raw, engineering), but the highest priority would be the default choice. Likewise, a table will use hints to determine the default order of columns. Each telemetry value description has an object defining hints. Keys in this this object represent the hint itself, and the value represents the weight of that hint. A lower weight means the hint has a higher priority. For example, multiple values could be hinted for use as the y axis of a plot (raw, engineering), but the highest priority would be the default choice. Likewise, a table will use hints to determine the default order of columns.
Known hints: Known hints:
* `domain`: Values with a `domain` hint will be used for the x-axis of a plot, and tables will render columns for these values first. * `domain`: Indicates that the value represents the "input" of a datum. Values with a `domain` hint will be used for the x-axis of a plot, and tables will render columns for these values first.
* `range`: Values with a `range` hint will be used as the y-axis on a plot, and tables will render columns for these values after the `domain` values. * `range`: Indicates that the value is the "output" of a datum. Values with a `range` hint will be used as the y-axis on a plot, and tables will render columns for these values after the `domain` values.
* `image`: Indicates that the value may be interpreted as the URL to an image file, in which case appropriate views will be made available. * `image`: Indicates that the value may be interpreted as the URL to an image file, in which case appropriate views will be made available.
##### The Time Conductor and Telemetry ##### The Time Conductor and Telemetry
@ -505,7 +511,7 @@ example:
} }
``` ```
This strategy says "I want the latest data point in this time range". A provider which recognizes this request should return only one value-- the latest-- in the requested time range. Depending on your back-end implementation, performing these queries in bulk can be a large performance increase. These are generally issued by views that are only capable of displaying a single value and only need to show the latest value. This strategy says "I want the lastest data point in this time range". A provider which recognizes this request should return only one value-- the latest-- in the requested time range. Depending on your back-end implementation, performing these queries in bulk can be a large performance increase. These are generally issued by views that are only capable of displaying a single value and only need to show the latest value.
##### `minmax` request strategy ##### `minmax` request strategy
@ -600,7 +606,7 @@ evaluator, take a look at `examples/generator/SinewaveLimitProvider.js`.
### Telemetry Consumer APIs **draft** ### Telemetry Consumer APIs **draft**
The APIs for requesting telemetry from Open MCT -- e.g. for use in custom views -- are currently in draft state and are being revised. If you'd like to experiment with them before they are finalized, please contact the team via the contact-us link on our website. The APIs for requesting telemetry from Open MCT -- e.g. for use in custom views -- are currently in draft state and are being revised. If you'd like to experiement with them before they are finalized, please contact the team via the contact-us link on our website.
## Time API ## Time API
@ -988,7 +994,7 @@ A common use case for indicators is to convey the state of some external system
persistence backend or HTTP server. So long as this system is accessible via HTTP request, persistence backend or HTTP server. So long as this system is accessible via HTTP request,
Open MCT provides a general purpose indicator to show whether the server is available and Open MCT provides a general purpose indicator to show whether the server is available and
returing a 2xx status code. The URL Status Indicator is made available as a default plugin. See returing a 2xx status code. The URL Status Indicator is made available as a default plugin. See
the [documentation](./src/plugins/URLIndicatorPlugin) for details on how to install and configure the [Included Plugins](#included-plugins) below for details on how to install and configure the
URL Status Indicator. URL Status Indicator.
### Creating a Simple Indicator ### Creating a Simple Indicator
@ -1027,7 +1033,7 @@ different colors to indicate status.
### Custom Indicators ### Custom Indicators
A completely custom indicator can be added by simply providing a DOM element to place alongside other indicators. A completely custom indicator can be added by simple providing a DOM element to place alongside other indicators.
``` javascript ``` javascript
var domNode = document.createElement('div'); var domNode = document.createElement('div');
@ -1040,3 +1046,59 @@ A completely custom indicator can be added by simply providing a DOM element to
element: domNode element: domNode
}); });
``` ```
## Included Plugins
Open MCT is packaged along with a few general-purpose plugins:
* `openmct.plugins.Conductor` provides a user interface for working with time
within the application. If activated, configuration must be provided. This is
detailed in the section on [Time Conductor Configuration](#time-conductor-configuration).
* `openmct.plugins.CouchDB` is an adapter for using CouchDB for persistence
of user-created objects. This is a constructor that takes the URL for the
CouchDB database as a parameter, e.g.
```javascript
openmct.install(openmct.plugins.CouchDB('http://localhost:5984/openmct'))
```
* `openmct.plugins.Elasticsearch` is an adapter for using Elasticsearch for
persistence of user-created objects. This is a
constructor that takes the URL for the Elasticsearch instance as a
parameter. eg.
```javascript
openmct.install(openmct.plugins.CouchDB('http://localhost:9200'))
```
* `openmct.plugins.Espresso` and `openmct.plugins.Snow` are two different
themes (dark and light) available for Open MCT. Note that at least one
of these themes must be installed for Open MCT to appear correctly.
* `openmct.plugins.URLIndicator` adds an indicator which shows the
availability of a URL with the following options:
- `url` : URL to indicate the status of
- `iconClass`: Icon to show in the status bar, defaults to `icon-database`, [list of all icons](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home?view=items)
- `interval`: Interval between checking the connection, defaults to `10000`
- `label` Name showing up as text in the status bar, defaults to url
```javascript
openmct.install(openmct.plugins.URLIndicator({
url: 'http://localhost:8080',
iconClass: 'check',
interval: 10000,
label: 'Localhost'
})
);
```
* `openmct.plugins.LocalStorage` provides persistence of user-created
objects in browser-local storage. This is particularly useful in
development environments.
* `openmct.plugins.MyItems` adds a top-level folder named "My Items"
when the application is first started, providing a place for a
user to store created items.
* `openmct.plugins.UTCTimeSystem` provides a default time system for Open MCT.
Generally, you will want to either install these plugins, or install
different plugins that provide persistence and an initial folder
hierarchy.
eg.
```javascript
openmct.install(openmct.plugins.LocalStorage());
openmct.install(openmct.plugins.MyItems());
```

View File

@ -103,7 +103,7 @@ the name chosen could not be mistaken for a topic or master branch.
### Merging ### Merging
When development is complete on an issue, the first step toward merging it When development is complete on an issue, the first step toward merging it
back into the master branch is to file a Pull Request (PR). The contributions back into the master branch is to file a Pull Request. The contributions
should meet code, test, and commit message standards as described below, should meet code, test, and commit message standards as described below,
and the pull request should include a completed author checklist, also and the pull request should include a completed author checklist, also
as described below. Pull requests may be assigned to specific team as described below. Pull requests may be assigned to specific team
@ -114,15 +114,6 @@ request. When the reviewer is satisfied, they should add a comment to
the pull request containing the reviewer checklist (from below) and complete the pull request containing the reviewer checklist (from below) and complete
the merge back to the master branch. the merge back to the master branch.
Additionally:
* Every pull request must link to the issue that it addresses. Eg. “Addresses #1234” or “Closes #1234”. This is the responsibility of the pull requests __author__. If no issue exists, create one.
* Every __author__ must include testing instructions. These instructions should identify the areas of code affected, and some minimal test steps. If addressing a bug, reproduction steps should be included, if they were not included in the original issue. If reproduction steps were included on the original issue, and are sufficient, refer to them.
* A pull request that closes an issue should say so in the description. Including the text “Closes #1234” will cause the linked issue to be automatically closed when the pull request is merged. This is the responsibility of the pull requests __author__.
* When a pull request is merged, and the corresponding issue closed, the __reviewer__ must add the tag “unverified” to the original issue. This will indicate that although the issue is closed, it has not been tested yet.
* Every PR must have two reviewers assigned, though only one approval is necessary for merge.
* Changes to API require approval by a senior developer.
* When creating a PR, it is the author's responsibility to apply any priority label from the issue to the PR as well. This helps with prioritization.
## Standards ## Standards
Contributions to Open MCT are expected to meet the following standards. Contributions to Open MCT are expected to meet the following standards.
@ -131,96 +122,89 @@ changes.
### Code Standards ### Code Standards
JavaScript sources in Open MCT must satisfy the ESLint rules defined in JavaScript sources in Open MCT must satisfy JSLint under its default
this repository. This is verified by the command line build. settings. This is verified by the command line build.
#### Code Guidelines #### Code Guidelines
The following guidelines are provided for anyone contributing source code to the Open MCT project: JavaScript sources in Open MCT should:
1. Write clean code. Heres a good summary - https://github.com/ryanmcdermott/clean-code-javascript. * Use four spaces for indentation. Tabs should not be used.
1. Include JSDoc for any exposed API (e.g. public methods, classes). * Include JSDoc for any exposed API (e.g. public methods, constructors).
1. Include non-JSDoc comments as-needed for explaining private variables, * Include non-JSDoc comments as-needed for explaining private variables,
methods, or algorithms when they are non-obvious. Otherwise code methods, or algorithms when they are non-obvious.
should be self-documenting. * Define one public class per script, expressed as a constructor function
1. Classes and Vue components should use camel case, first letter capitalized returned from an AMD-style module.
* Follow “Java-like” naming conventions. These includes:
* Classes should use camel case, first letter capitalized
(e.g. SomeClassName). (e.g. SomeClassName).
1. Methods, variables, fields, events, and function names should use camelCase, * Methods, variables, fields, and function names should use camel case,
first letter lower-case (e.g. someVariableName). first letter lower-case (e.g. someVariableName).
1. Source files that export functions should use camelCase, first letter lower-case (eg. testTools.js) * Constants (variables or fields which are meant to be declared and
1. Constants (variables or fields which are meant to be declared and
initialized statically, and never changed) should use only capital initialized statically, and never changed) should use only capital
letters, with underscores between words (e.g. SOME_CONSTANT). They should always be declared as `const`s letters, with underscores between words (e.g. SOME_CONSTANT).
1. File names should be the name of the exported class, plus a .js extension * File names should be the name of the exported class, plus a .js extension
(e.g. SomeClassName.js). (e.g. SomeClassName.js).
1. Avoid anonymous functions, except when functions are short (one or two lines) * Avoid anonymous functions, except when functions are short (a few lines)
and their inclusion makes sense within the flow of the code and/or their inclusion makes sense within the flow of the code
(e.g. as arguments to a forEach call). Anonymous functions should always be arrow functions. (e.g. as arguments to a forEach call).
1. Named functions are preferred over functions assigned to variables. * Avoid deep nesting (especially of functions), except where necessary
eg.
```JavaScript
function renameObject(object, newName) {
Object.name = newName;
}
```
is preferable to
```JavaScript
const rename = (object, newName) => {
Object.name = newName;
}
```
1. Avoid deep nesting (especially of functions), except where necessary
(e.g. due to closure scope). (e.g. due to closure scope).
1. End with a single new-line character. * End with a single new-line character.
1. Always use ES6 `Class`es and inheritence rather than the pre-ES6 prototypal * Expose public methods by declaring them on the class's prototype.
pattern. * Within a given function's scope, do not mix declarations and imperative
1. Within a given function's scope, do not mix declarations and imperative
code, and present these in the following order: code, and present these in the following order:
* First, variable declarations and initialization. * First, variable declarations and initialization.
* Secondly, imperative statements. * Second, function declarations.
* Finally, the returned value. A single return statement at the end of the function should be used, except where an early return would improve code clarity. * Third, imperative statements.
1. Avoid the use of "magic" values. * Finally, the returned value.
eg.
```JavaScript
Const UNAUTHORIZED = 401
if (responseCode === UNAUTHORIZED)
```
is preferable to
```JavaScript
if (responseCode === 401)
```
1. Use the ternary operator only for simple cases such as variable assignment. Nested ternaries should be avoided in all cases.
1. Test specs should reside alongside the source code they test, not in a separate directory.
1. Organize code by feature, not by type.
eg.
```
- telemetryTable
- row
TableRow.js
TableRowCollection.js
TableRow.vue
- column
TableColumn.js
TableColumn.vue
plugin.js
pluginSpec.js
```
is preferable to
```
- telemetryTable
- components
TableRow.vue
TableColumn.vue
- collections
TableRowCollection.js
TableColumn.js
TableRow.js
plugin.js
pluginSpec.js
```
Deviations from Open MCT code style guidelines require two-party agreement, Deviations from Open MCT code style guidelines require two-party agreement,
typically from the author of the change and its reviewer. typically from the author of the change and its reviewer.
#### Code Example
```js
/*global define*/
/**
* Bundles should declare themselves as namespaces in whichever source
* file is most like the "main point of entry" to the bundle.
* @namespace some/bundle
*/
define(
['./OtherClass'],
function (OtherClass) {
"use strict";
/**
* A summary of how to use this class goes here.
*
* @constructor
* @memberof some/bundle
*/
function ExampleClass() {
}
// Methods which are not intended for external use should
// not have JSDoc (or should be marked @private)
ExampleClass.prototype.privateMethod = function () {
};
/**
* A summary of this method goes here.
* @param {number} n a parameter
* @returns {number} a return value
*/
ExampleClass.prototype.publicMethod = function (n) {
return n * 2;
}
return ExampleClass;
}
);
```
### Test Standards ### Test Standards
Automated testing shall occur whenever changes are merged into the main Automated testing shall occur whenever changes are merged into the main
@ -308,7 +292,6 @@ checklist).
2. Unit tests included and/or updated with changes? 2. Unit tests included and/or updated with changes?
3. Command line build passes? 3. Command line build passes?
4. Changes have been smoke-tested? 4. Changes have been smoke-tested?
5. Testing instructions included?
### Reviewer Checklist ### Reviewer Checklist
@ -316,4 +299,3 @@ checklist).
2. Appropriate unit tests included? 2. Appropriate unit tests included?
3. Code style and in-line documentation are appropriate? 3. Code style and in-line documentation are appropriate?
4. Commit messages meet standards? 4. Commit messages meet standards?
5. Has associated issue been labelled `unverified`? (only applicable if this PR closes the issue)

View File

@ -1,7 +0,0 @@
# Open MCT License
Open MCT, Copyright (c) 2014-2019, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.
Open MCT is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

691
LICENSES.md Normal file
View File

@ -0,0 +1,691 @@
# Open MCT Licenses
Open MCT, Copyright (c) 2014-2017, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.
Open MCT is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Open MCT includes source code licensed under additional open source licenses as follows.
## Software Components Licenses
This software includes components released under the following licenses:
---
### SuperSocket
#### Info
* Link: https://supersocket.codeplex.com/
* Version: 0.9.0.2
* Author: Kerry Jiang
* Description: Supports SuperWebSocket
#### License
Copyright 2012 Kerry Jiang (kerry-jiang@hotmail.com)
SuperSocket 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.
---
### SuperWebSocket
#### Info
* Link: https://superswebocket.codeplex.com/
* Version: 0.9.0.2
* Author: Kerry Jiang
* Description: WebSocket implementation for client-server communication
#### License
Copyright 2010-2013 Kerry Jiang (kerry-jiang@hotmail.com)
SuperWebSocket 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.
---
### log4net
#### Info
* Link: http://logging.apache.org/log4net/
* Version: 1.2.13
* Author: Apache Software Foundation
* Description: Logging.
#### License
Copyright © 2004-2015 Apache Software Foundation.
log4net 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.
---
### Blanket.js
#### Info
* Link: http://blanketjs.org/
* Version: 1.1.5
* Author: Alex Seville
* Description: Code coverage measurement and reporting
#### License
Copyright (c) 2013 Alex Seville
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
Copyright (c) 2008-2011 Pivotal Labs
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.22
* 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.
---
### requirejs-text
#### Info
* Link: https://github.com/requirejs/text
* Version: 2.0.14
* Author: The Dojo Foundation
* Description: Text loading plugin for RequireJS
#### License
Copyright (c) 2010-2014, 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.4.4
* 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.4.4
* 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: 3.0.2
* 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: 3.0.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.7
* Author: Robert Kieffer
* Description: Unique identifer generation.
#### License
Copyright (c) 2010-2012 Robert Kieffer
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: https://github.com/necolas/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.11.1
* 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.
---
### moment-duration-format
#### Info
* Link: https://github.com/jsmreese/moment-duration-format
* Version: 1.3.0
* Authors: John Madhavan-Reese
* Description: Duration parsing/formatting
#### License
Copyright 2014 John Madhavan-Reese
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.
---
### CSV.js
#### Info
* Link: https://github.com/knrz/CSV.js
* Version: 3.6.4
* Authors: Kash Nouroozi
* Description: Encoder for CSV (comma separated values) export
#### License
Copyright (c) 2014 Kash Nouroozi
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.
---
### FileSaver.js
#### Info
* Link: https://github.com/eligrey/FileSaver.js/
* Version: 0.0.2
* Authors: Eli Grey
* Description: File download initiator (for file exports)
#### License
Copyright © 2015 Eli Grey.
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.
---
### Zepto
#### Info
* Link: http://zeptojs.com/
* Version: 1.1.6
* Authors: Thomas Fuchs
* Description: DOM manipulation
#### License
Copyright (c) 2010-2016 Thomas Fuchs
http://zeptojs.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.
---
### Json.NET
#### Info
* Link: http://www.newtonsoft.com/json
* Version: 6.0.8
* Author: Newtonsoft
* Description: JSON serialization/deserialization
#### License
Copyright (c) 2007 James Newton-King
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.
---
### Nancy
#### Info
* Link: http://nancyfx.org
* Version: 0.23.2
* Author: Andreas Håkansson, Steven Robbins and contributors
* Description: Embedded web server
#### License
Copyright © 2010 Andreas Håkansson, Steven Robbins 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.
---
### Nancy.Hosting.Self
#### Info
* Link: http://nancyfx.org
* Version: 0.23.2
* Author: Andreas Håkansson, Steven Robbins and contributors
* Description: Embedded web server
#### License
Copyright © 2010 Andreas Håkansson, Steven Robbins 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.
---
### Almond
* Link: https://github.com/requirejs/almond
* Version: 0.3.3
* Author: jQuery Foundation
* Description: Lightweight RequireJS replacement for builds
#### License
Copyright jQuery Foundation and other contributors, https://jquery.org/
This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/requirejs/almond
The following license applies to all parts of this software except as
documented below:
====
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.
====
Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code displayed within the prose of the
documentation.
CC0: http://creativecommons.org/publicdomain/zero/1.0/
====
Files located in the node_modules directory, and certain utilities used
to build or test the software in the test and dist directories, are
externally maintained libraries used by this software which have their own
licenses; we recommend you read them, as their terms may differ from the
terms above.
### Lodash
* Link: https://lodash.com
* Version: 3.10.1
* Author: Dojo Foundation
* Description: Utility functions
#### License
Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
Based on Underscore.js, copyright 2009-2015 Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.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.
### EventEmitter3
* Link: https://github.com/primus/eventemitter3
* Version: 1.2.0
* Author: Arnout Kazemier
* Description: Event-driven programming support
#### License
The MIT License (MIT)
Copyright (c) 2014 Arnout Kazemier
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.

View File

@ -9,6 +9,26 @@ Please visit our [Official Site](https://nasa.github.io/openmct/) and [Getting S
Try Open MCT now with our [live demo](https://openmct-demo.herokuapp.com/). Try Open MCT now with our [live demo](https://openmct-demo.herokuapp.com/).
![Demo](https://nasa.github.io/openmct/static/res/images/Open-MCT.Browse.Layout.Mars-Weather-1.jpg) ![Demo](https://nasa.github.io/openmct/static/res/images/Open-MCT.Browse.Layout.Mars-Weather-1.jpg)
## New API
A simpler, [easier-to-use API](https://nasa.github.io/openmct/docs/api/)
has been added to Open MCT. Changes in this
API include a move away from a declarative system of JSON configuration files
towards an imperative system based on function calls. Developers will be able
to extend and build on Open MCT by making direct function calls to a public
API. Open MCT is also being refactored to minimize the dependencies that using
Open MCT imposes on developers, such as the current requirement to use
AngularJS.
This new API has not yet been heavily used and is likely to contain defects.
You can help by trying it out, and reporting any issues you encounter
using our GitHub issue tracker. Such issues may include bugs, suggestions,
missing documentation, or even just requests for help if you're having
trouble.
We want Open MCT to be as easy to use, install, run, and develop for as
possible, and your feedback will help us get there!
## Building and Running Open MCT Locally ## Building and Running Open MCT Locally
Building and running Open MCT in your local dev environment is very easy. Be sure you have [Git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/) installed, then follow the directions below. Need additional information? Check out the [Getting Started](https://nasa.github.io/openmct/getting-started/) page on our website. Building and running Open MCT in your local dev environment is very easy. Be sure you have [Git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/) installed, then follow the directions below. Need additional information? Check out the [Getting Started](https://nasa.github.io/openmct/getting-started/) page on our website.
@ -28,14 +48,9 @@ Building and running Open MCT in your local dev environment is very easy. Be sur
Open MCT is now running, and can be accessed by pointing a web browser at [http://localhost:8080/](http://localhost:8080/) Open MCT is now running, and can be accessed by pointing a web browser at [http://localhost:8080/](http://localhost:8080/)
## Open MCT v1.0.0
This represents a major overhaul of Open MCT with significant changes under the hood. We aim to maintain backward compatibility but if you do find compatibility issues, please let us know by filing an issue in this repository. If you are having major issues with v1.0.0 please check-out the v0.14.0 tag until we can resolve them for you.
If you are migrating an application built with Open MCT as a dependency to v1.0.0 from an earlier version, please refer to [our migration guide](https://nasa.github.io/openmct/documentation/migration-guide).
## Documentation ## Documentation
Documentation is available on the [Open MCT website](https://nasa.github.io/openmct/documentation/). Documentation is available on the [Open MCT website](https://nasa.github.io/openmct/documentation/). The documentation can also be built locally.
### Examples ### Examples
@ -43,29 +58,48 @@ The clearest examples for developing Open MCT plugins are in the
[tutorials](https://github.com/nasa/openmct-tutorial) provided in [tutorials](https://github.com/nasa/openmct-tutorial) provided in
our documentation. our documentation.
We want Open MCT to be as easy to use, install, run, and develop for as For a practical example of a telemetry adapter, see David Hudson's
possible, and your feedback will help us get there! Feedback can be provided via [GitHub issues](https://github.com/nasa/openmct/issues), or by emailing us at [arc-dl-openmct@mail.nasa.gov](mailto:arc-dl-openmct@mail.nasa.gov). [Kerbal Space Program plugin](https://github.com/hudsonfoo/kerbal-openmct),
which allows [Kerbal Space Program](https://kerbalspaceprogram.com) players
to build and use displays for their own missions in Open MCT.
## Building Applications With Open MCT Additional examples are available in the `examples` hierarchy of this
repository; however, be aware that these examples are
[not fully-documented](https://github.com/nasa/openmct/issues/846), so
the tutorials will likely serve as a better starting point.
Open MCT is built using [`npm`](http://npmjs.com/) and [`webpack`](https://webpack.js.org/). ### Building the Open MCT Documentation Locally
Open MCT's documentation is generated by an
[npm](https://www.npmjs.com/)-based build. It has additional dependencies that
may not be available on every platform and thus is not covered in the standard
npm install. Ensure your system has [libcairo](http://cairographics.org/)
installed and then run the following commands:
See our documentation for a guide on [building Applications with Open MCT](https://github.com/nasa/openmct/blob/master/API.md#starting-an-open-mct-application). * `npm install`
* `npm install canvas nomnoml`
* `npm run docs`
## Plugins Documentation will be generated in `target/docs`.
Open MCT can be extended via plugins that make calls to the Open MCT API. A plugin is a group ## Deploying Open MCT
of software components (including source code and resources such as images and HTML templates)
that is intended to be added or removed as a single unit.
As well as providing an extension mechanism, most of the core Open MCT codebase is also Open MCT is built using [`npm`](http://npmjs.com/)
written as plugins.
For information on writing plugins, please see [our API documentation](https://github.com/nasa/openmct/blob/master/API.md#plugins). To build Open MCT for deployment:
`npm run prepare`
This will compile and minify JavaScript sources, as well as copy over assets.
The contents of the `dist` folder will contain a runnable Open MCT
instance (e.g. by starting an HTTP server in that directory), including:
* `openmct.js` - Open MCT source code.
* `openmct.css` - Basic styles to load to prevent a FOUC.
* `index.html`, an example to run Open MCT in the basic configuration.
## Tests ## Tests
Tests are written for [Jasmine 3](https://jasmine.github.io/api/3.1/global) Tests are written for [Jasmine 3](http://jasmine.github.io/)
and run by [Karma](http://karma-runner.github.io). To run: and run by [Karma](http://karma-runner.github.io). To run:
`npm test` `npm test`
@ -81,7 +115,7 @@ naming convention is otherwise the same.)
### Test Reporting ### Test Reporting
When `npm test` is run, test results will be written as HTML to When `npm test` is run, test results will be written as HTML to
`dist/reports/tests/`. Code coverage information is written to `dist/reports/coverage`. `target/tests`. Code coverage information is written to `target/coverage`.
# Glossary # Glossary
@ -91,8 +125,11 @@ addressed (either by updating this glossary or changing code to reflect
correct usage.) Other developer documentation, particularly in-line correct usage.) Other developer documentation, particularly in-line
documentation, may presume an understanding of these terms. documentation, may presume an understanding of these terms.
* _plugin_: A plugin is a removable, reusable grouping of software elements. * _bundle_: A bundle is a removable, reusable grouping of software elements.
The application is composed of plugins. The application is composed of bundles. Plug-ins are bundles. For more
information, refer to framework documentation (under `platform/framework`.)
* _capability_: An object which exposes dynamic behavior or non-persistent
state associated with a domain object.
* _composition_: In the context of a domain object, this refers to the set of * _composition_: In the context of a domain object, this refers to the set of
other domain objects that compose or are contained by that object. A domain other domain objects that compose or are contained by that object. A domain
object's composition is the set of domain objects that should appear object's composition is the set of domain objects that should appear
@ -107,8 +144,13 @@ documentation, may presume an understanding of these terms.
* _domain object_: A meaningful object to the user; a distinct thing in * _domain object_: A meaningful object to the user; a distinct thing in
the work support by Open MCT. Anything that appears in the left-hand the work support by Open MCT. Anything that appears in the left-hand
tree is a domain object. tree is a domain object.
* _identifier_: A tuple consisting of a namespace and a key, which together uniquely * _extension_: An extension is a unit of functionality exposed to the
identifies a domain object. platform in a declarative fashion by a bundle. For more
information, refer to framework documentation (under `platform/framework`.)
* _id_: A string which uniquely identifies a domain object.
* _key_: When used as an object property, this refers to the machine-readable
identifier for a specific thing in a set of things. (Most often used in the
context of extensions or other similar application-specific object sets.)
* _model_: The persistent state associated with a domain object. A domain * _model_: The persistent state associated with a domain object. A domain
object's model is a JavaScript object which can be converted to JSON object's model is a JavaScript object which can be converted to JSON
without losing information (that is, it contains no methods.) without losing information (that is, it contains no methods.)
@ -120,5 +162,7 @@ documentation, may presume an understanding of these terms.
a user clicks on a domain object in the tree, they are _navigating_ to a user clicks on a domain object in the tree, they are _navigating_ to
it, and it is thereafter considered the _navigated_ object (until the it, and it is thereafter considered the _navigated_ object (until the
user makes another such choice.) user makes another such choice.)
* _namespace_: A name used to identify a persistence store. A running open MCT * _space_: A name used to identify a persistence store. Interactions with
application could potentially use multiple persistence stores, with the persistence will generally involve a `space` parameter in some form, to
distinguish multiple persistence stores from one another (for cases
where there are multiple valid persistence locations available.)

2
app.js
View File

@ -16,7 +16,7 @@ const request = require('request');
// Defaults // Defaults
options.port = options.port || options.p || 8080; options.port = options.port || options.p || 8080;
options.host = options.host || 'localhost'; options.host = options.host || options.h || 'localhost';
options.directory = options.directory || options.D || '.'; options.directory = options.directory || options.D || '.';
// Show command line options // Show command line options

View File

@ -1,5 +1,5 @@
<!-- <!--
Open MCT, Copyright (c) 2014-2020, United States Government Open MCT, Copyright (c) 2014-2018, United States Government
as represented by the Administrator of the National Aeronautics and Space as represented by the Administrator of the National Aeronautics and Space
Administration. All rights reserved. Administration. All rights reserved.

View File

@ -1,5 +1,5 @@
/***************************************************************************** /*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, United States Government * Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space * as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved. * Administration. All rights reserved.
* *

View File

@ -33,5 +33,5 @@ As we transition to a new API, the following documentation for the old API
* The [Developer's Guide](guide/) goes into more detail about how to use the * The [Developer's Guide](guide/) goes into more detail about how to use the
platform and the functionality that it provides. platform and the functionality that it provides.
* The [Tutorials](https://github.com/nasa/openmct-tutorial) give examples of extending the platform to add * The [Tutorials](tutorials/) give examples of extending the platform to add
functionality, and integrate with data sources. functionality, and integrate with data sources.

View File

@ -125,22 +125,3 @@ A release is not closed until both categories have been performed on
the latest snapshot of the software, _and_ no issues labelled as the latest snapshot of the software, _and_ no issues labelled as
["blocker" or "critical"](https://github.com/nasa/openmctweb/blob/master/CONTRIBUTING.md#issue-reporting) ["blocker" or "critical"](https://github.com/nasa/openmctweb/blob/master/CONTRIBUTING.md#issue-reporting)
remain open. remain open.
### Testathons
Testathons can be used as a means of performing per-sprint and per-release testing.
#### Timing
For per-sprint testing, a testathon is typically performed at the beginning of the third week of a sprint, and again later that week to verify any fixes. For per-release testing, a testathon is typically performed prior to any formal testing processes that are applicable to that release.
#### Process
1. Prior to the scheduled testathon, a list will be compiled of all issues that are closed and unverified.
2. For each issue, testers should review the associated PR for testing instructions. See the contributing guide for instructions on [pull requests](https://github.com/nasa/openmct/blob/master/CONTRIBUTING.md#merging).
3. As each issue is verified via testing, any team members testing it should leave a comment on that issue indicating that it has been verified fixed.
4. If a bug is found that relates to an issue being tested, notes should be included on the associated issue, and the issue should be reopened. Bug notes should include reproduction steps.
5. For any bugs that are not obviously related to any of the issues under test, a new issue should be created with details about the bug, including reproduction steps. If unsure about whether a bug relates to an issue being tested, just create a new issue.
6. At the end of the testathon, triage will take place, where all tested issues will be reviewed.
7. If verified fixed, an issue will remain closed, and will have the “unverified” label removed.
8. For any bugs found, a severity will be assigned.
9. A second testathon will be scheduled for later in the week that will aim to address all issues identified as blockers, as well as any other issues scoped by the team during triage.
10. Any issues that were not tested will remain "unverified" and will be picked up in the next testathon.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

3309
docs/src/tutorials/index.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -22,15 +22,15 @@
/*global define*/ /*global define*/
define([ define([
"./src/EventTelemetryProvider" "./src/EventTelemetryProvider",
'legacyRegistry'
], function ( ], function (
EventTelemetryProvider EventTelemetryProvider,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/eventGenerator", {
name:"example/eventGenerator",
definition: {
"name": "Event Message Generator", "name": "Event Message Generator",
"description": "For development use. Creates sample event message data that mimics a live data stream.", "description": "For development use. Creates sample event message data that mimics a live data stream.",
"extensions": { "extensions": {
@ -76,6 +76,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -34,9 +34,11 @@ define(
* @constructor * @constructor
*/ */
function EventTelemetryProvider($q, $timeout) { function EventTelemetryProvider($q, $timeout) {
var subscriptions = [], var
subscriptions = [],
genInterval = 1000, genInterval = 1000,
generating = false; generating = false,
id = Math.random() * 100000;
// //
function matchesSource(request) { function matchesSource(request) {
@ -45,6 +47,7 @@ define(
// Used internally; this will be repacked by doPackage // Used internally; this will be repacked by doPackage
function generateData(request) { function generateData(request) {
//console.log("generateData " + (Date.now() - startTime).toString());
return { return {
key: request.key, key: request.key,
telemetry: new EventTelemetry(request, genInterval) telemetry: new EventTelemetry(request, genInterval)

View File

@ -58,15 +58,15 @@ define([], function () {
row, row,
i; i;
function copyDomainsToRow(telemetryRow, index) { function copyDomainsToRow(row, index) {
domains.forEach(function (domain) { domains.forEach(function (domain) {
telemetryRow[domain.name] = series.getDomainValue(index, domain.key); row[domain.name] = series.getDomainValue(index, domain.key);
}); });
} }
function copyRangesToRow(telemetryRow, index) { function copyRangesToRow(row, index) {
ranges.forEach(function (range) { ranges.forEach(function (range) {
telemetryRow[range.name] = series.getRangeValue(index, range.key); row[range.name] = series.getRangeValue(index, range.key);
}); });
} }

View File

@ -22,13 +22,12 @@
/*global define*/ /*global define*/
define([ define([
'legacyRegistry',
'./ExportTelemetryAsCSVAction' './ExportTelemetryAsCSVAction'
], function (ExportTelemetryAsCSVAction) { ], function (legacyRegistry, ExportTelemetryAsCSVAction) {
"use strict"; "use strict";
return { legacyRegistry.register("example/export", {
name:"example/export",
definition: {
"name": "Example of using CSV Export", "name": "Example of using CSV Export",
"extensions": { "extensions": {
"actions": [ "actions": [
@ -38,10 +37,9 @@ define([
"implementation": ExportTelemetryAsCSVAction, "implementation": ExportTelemetryAsCSVAction,
"category": "contextual", "category": "contextual",
"cssClass": "icon-download", "cssClass": "icon-download",
"depends": ["exportService"] "depends": [ "exportService" ]
} }
] ]
} }
} });
};
}); });

View File

@ -22,15 +22,15 @@
/*global define*/ /*global define*/
define([ define([
"./src/ExampleFormController" "./src/ExampleFormController",
'legacyRegistry'
], function ( ], function (
ExampleFormController ExampleFormController,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/forms", {
name:"example/forms",
definition: {
"name": "Declarative Forms example", "name": "Declarative Forms example",
"sources": "src", "sources": "src",
"extensions": { "extensions": {
@ -49,6 +49,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -9,8 +9,7 @@ define([
values: [ values: [
{ {
key: "name", key: "name",
name: "Name", name: "Name"
format: "string"
}, },
{ {
key: "utc", key: "utc",
@ -50,8 +49,7 @@ define([
values: [ values: [
{ {
key: "name", key: "name",
name: "Name", name: "Name"
format: "string"
}, },
{ {
key: "utc", key: "utc",
@ -100,7 +98,7 @@ define([
}; };
GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) { GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) {
return Object.assign( return _.extend(
{}, {},
domainObject.telemetry, domainObject.telemetry,
METADATA_BY_TYPE[domainObject.type] METADATA_BY_TYPE[domainObject.type]

View File

@ -31,7 +31,6 @@ define([
period: 10, period: 10,
offset: 0, offset: 0,
dataRateInHz: 1, dataRateInHz: 1,
randomness: 0,
phase: 0 phase: 0
}; };
@ -54,7 +53,6 @@ define([
'offset', 'offset',
'dataRateInHz', 'dataRateInHz',
'phase', 'phase',
'randomness'
]; ];
request = request || {}; request = request || {};

View File

@ -89,7 +89,7 @@ define([
WorkerInterface.prototype.subscribe = function (request, cb) { WorkerInterface.prototype.subscribe = function (request, cb) {
function callback(message) { function callback(message) {
cb(message.data); cb(message.data);
} };
var messageId = this.dispatch('subscribe', request, callback); var messageId = this.dispatch('subscribe', request, callback);

View File

@ -65,8 +65,8 @@
name: data.name, name: data.name,
utc: nextStep, utc: nextStep,
yesterday: nextStep - 60*60*24*1000, yesterday: nextStep - 60*60*24*1000,
sin: sin(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness), sin: sin(nextStep, data.period, data.amplitude, data.offset, data.phase),
cos: cos(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness) cos: cos(nextStep, data.period, data.amplitude, data.offset, data.phase)
} }
}); });
nextStep += step; nextStep += step;
@ -84,10 +84,10 @@
function onRequest(message) { function onRequest(message) {
var request = message.data; var request = message.data;
if (request.end === undefined) { if (request.end == undefined) {
request.end = Date.now(); request.end = Date.now();
} }
if (request.start === undefined) { if (request.start == undefined){
request.start = request.end - FIFTEEN_MINUTES; request.start = request.end - FIFTEEN_MINUTES;
} }
@ -99,7 +99,6 @@
var offset = request.offset; var offset = request.offset;
var dataRateInHz = request.dataRateInHz; var dataRateInHz = request.dataRateInHz;
var phase = request.phase; var phase = request.phase;
var randomness = request.randomness;
var step = 1000 / dataRateInHz; var step = 1000 / dataRateInHz;
var nextStep = start - (start % step) + step; var nextStep = start - (start % step) + step;
@ -111,8 +110,8 @@
name: request.name, name: request.name,
utc: nextStep, utc: nextStep,
yesterday: nextStep - 60*60*24*1000, yesterday: nextStep - 60*60*24*1000,
sin: sin(nextStep, period, amplitude, offset, phase, randomness), sin: sin(nextStep, period, amplitude, offset, phase),
cos: cos(nextStep, period, amplitude, offset, phase, randomness) cos: cos(nextStep, period, amplitude, offset, phase)
}); });
} }
self.postMessage({ self.postMessage({
@ -121,14 +120,14 @@
}); });
} }
function cos(timestamp, period, amplitude, offset, phase, randomness) { function cos(timestamp, period, amplitude, offset, phase) {
return amplitude * return amplitude *
Math.cos(phase + (timestamp / period / 1000 * Math.PI * 2)) + (amplitude * Math.random() * randomness) + offset; Math.cos(phase + (timestamp / period / 1000 * Math.PI * 2)) + offset;
} }
function sin(timestamp, period, amplitude, offset, phase, randomness) { function sin(timestamp, period, amplitude, offset, phase) {
return amplitude * return amplitude *
Math.sin(phase + (timestamp / period / 1000 * Math.PI * 2)) + (amplitude * Math.random() * randomness) + offset; Math.sin(phase + (timestamp / period / 1000 * Math.PI * 2)) + offset;
} }
function sendError(error, message) { function sendError(error, message) {

View File

@ -33,7 +33,7 @@ define([
GeneratorMetadataProvider GeneratorMetadataProvider
) { ) {
return function (openmct) { return function(openmct){
openmct.types.addType("example.state-generator", { openmct.types.addType("example.state-generator", {
name: "State Generator", name: "State Generator",
@ -122,17 +122,6 @@ define([
"telemetry", "telemetry",
"phase" "phase"
] ]
},
{
name: "Randomness",
control: "numberfield",
cssClass: "l-input-sm l-numeric",
key: "randomness",
required: true,
property: [
"telemetry",
"randomness"
]
} }
], ],
initialize: function (object) { initialize: function (object) {
@ -141,8 +130,7 @@ define([
amplitude: 1, amplitude: 1,
offset: 0, offset: 0,
dataRateInHz: 1, dataRateInHz: 1,
phase: 0, phase: 0
randomness: 0
}; };
} }
}); });

View File

@ -22,15 +22,15 @@
/*global define*/ /*global define*/
define([ define([
"./src/ExampleIdentityService" "./src/ExampleIdentityService",
'legacyRegistry'
], function ( ], function (
ExampleIdentityService ExampleIdentityService,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/identity", {
name:"example/identity",
definition: {
"extensions": { "extensions": {
"components": [ "components": [
{ {
@ -44,6 +44,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -22,7 +22,7 @@
define([ define([
], function ( ], function(
) { ) {
function ImageryPlugin() { function ImageryPlugin() {
@ -52,7 +52,6 @@ define([
return { return {
name: name, name: name,
utc: Math.floor(timestamp / 5000) * 5000, utc: Math.floor(timestamp / 5000) * 5000,
local: Math.floor(timestamp / 5000) * 5000,
url: IMAGE_SAMPLES[Math.floor(timestamp / 5000) % IMAGE_SAMPLES.length] url: IMAGE_SAMPLES[Math.floor(timestamp / 5000) % IMAGE_SAMPLES.length]
}; };
} }
@ -66,7 +65,7 @@ define([
callback(pointForTimestamp(Date.now(), domainObject.name)); callback(pointForTimestamp(Date.now(), domainObject.name));
}, 5000); }, 5000);
return function () { return function (interval) {
clearInterval(interval); clearInterval(interval);
}; };
} }
@ -79,7 +78,7 @@ define([
}, },
request: function (domainObject, options) { request: function (domainObject, options) {
var start = options.start; var start = options.start;
var end = Math.min(options.end, Date.now()); var end = options.end;
var data = []; var data = [];
while (start <= end && data.length < 5000) { while (start <= end && data.length < 5000) {
data.push(pointForTimestamp(start, domainObject.name)); data.push(pointForTimestamp(start, domainObject.name));
@ -119,14 +118,6 @@ define([
name: 'Time', name: 'Time',
key: 'utc', key: 'utc',
format: 'utc', format: 'utc',
hints: {
domain: 2
}
},
{
name: 'Local Time',
key: 'local',
format: 'local-format',
hints: { hints: {
domain: 1 domain: 1
} }

View File

@ -21,12 +21,16 @@
*****************************************************************************/ *****************************************************************************/
/*global define*/ /*global define*/
define([], function () { define([
'legacyRegistry'
], function (
legacyRegistry
) {
"use strict"; "use strict";
return { legacyRegistry.register("example/mobile", {
name:"example/mobile",
definition: {
"name": "Mobile", "name": "Mobile",
"description": "Allows elements with pertinence to mobile usage and development", "description": "Allows elements with pertinence to mobile usage and development",
"extensions": { "extensions": {
@ -37,6 +41,5 @@ define([], function () {
} }
] ]
} }
} });
};
}); });

View File

@ -24,16 +24,17 @@
define([ define([
"./src/RemsTelemetryServerAdapter", "./src/RemsTelemetryServerAdapter",
"./src/RemsTelemetryModelProvider", "./src/RemsTelemetryModelProvider",
"./src/RemsTelemetryProvider" "./src/RemsTelemetryProvider",
'legacyRegistry',
"module"
], function ( ], function (
RemsTelemetryServerAdapter, RemsTelemetryServerAdapter,
RemsTelemetryModelProvider, RemsTelemetryModelProvider,
RemsTelemetryProvider RemsTelemetryProvider,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/msl", {
name:"example/msl",
definition: {
"name" : "Mars Science Laboratory Data Adapter", "name" : "Mars Science Laboratory Data Adapter",
"extensions" : { "extensions" : {
"types": [ "types": [
@ -109,7 +110,6 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -22,7 +22,7 @@
/*global define*/ /*global define*/
define( define(
function () { function (){
"use strict"; "use strict";
var PREFIX = "msl_tlm:", var PREFIX = "msl_tlm:",
@ -32,20 +32,20 @@ define(
string: "string" string: "string"
}; };
function RemsTelemetryModelProvider(adapter) { function RemsTelemetryModelProvider(adapter){
function isRelevant(id) { function isRelevant(id) {
return id.indexOf(PREFIX) === 0; return id.indexOf(PREFIX) === 0;
} }
function makeId(element) { function makeId(element){
return PREFIX + element.identifier; return PREFIX + element.identifier;
} }
function buildTaxonomy(dictionary) { function buildTaxonomy(dictionary){
var models = {}; var models = {};
function addMeasurement(measurement, parent) { function addMeasurement(measurement, parent){
var format = FORMAT_MAPPINGS[measurement.type]; var format = FORMAT_MAPPINGS[measurement.type];
models[makeId(measurement)] = { models[makeId(measurement)] = {
type: "msl.measurement", type: "msl.measurement",
@ -73,12 +73,12 @@ define(
location: spacecraftId, location: spacecraftId,
composition: measurements.map(makeId) composition: measurements.map(makeId)
}; };
measurements.forEach(function (measurement) { measurements.forEach(function(measurement) {
addMeasurement(measurement, instrumentId); addMeasurement(measurement, instrumentId);
}); });
} }
(dictionary.instruments || []).forEach(function (instrument) { (dictionary.instruments || []).forEach(function(instrument) {
addInstrument(instrument, "msl:curiosity"); addInstrument(instrument, "msl:curiosity");
}); });
return models; return models;

View File

@ -72,10 +72,10 @@ define (
* This data source does not support real-time subscriptions * This data source does not support real-time subscriptions
*/ */
RemsTelemetryProvider.prototype.subscribe = function (callback, requests) { RemsTelemetryProvider.prototype.subscribe = function (callback, requests) {
return function () {}; return function() {};
}; };
RemsTelemetryProvider.prototype.unsubscribe = function (callback, requests) { RemsTelemetryProvider.prototype.unsubscribe = function (callback, requests) {
return function () {}; return function() {};
}; };
return RemsTelemetryProvider; return RemsTelemetryProvider;

View File

@ -54,7 +54,7 @@ define(
* @returns {number} A count of the number of data values available in * @returns {number} A count of the number of data values available in
* this series * this series
*/ */
RemsTelemetrySeries.prototype.getPointCount = function () { RemsTelemetrySeries.prototype.getPointCount = function() {
return this.data.length; return this.data.length;
}; };
/** /**
@ -64,7 +64,7 @@ define(
* @param index * @param index
* @returns {number} the time value in ms since 1 January 1970 * @returns {number} the time value in ms since 1 January 1970
*/ */
RemsTelemetrySeries.prototype.getDomainValue = function (index) { RemsTelemetrySeries.prototype.getDomainValue = function(index) {
return this.data[index].date; return this.data[index].date;
}; };
@ -75,7 +75,7 @@ define(
* value of. * value of.
* @returns {number} A floating point number * @returns {number} A floating point number
*/ */
RemsTelemetrySeries.prototype.getRangeValue = function (index) { RemsTelemetrySeries.prototype.getRangeValue = function(index) {
return this.data[index].value; return this.data[index].value;
}; };

View File

@ -68,18 +68,18 @@ define(
* given request ID. * given request ID.
* @private * @private
*/ */
RemsTelemetryServerAdapter.prototype.requestHistory = function (request) { RemsTelemetryServerAdapter.prototype.requestHistory = function(request) {
var self = this, var self = this,
id = request.key; id = request.key;
var dataTransforms = this.dataTransforms; var dataTransforms = this.dataTransforms;
function processResponse(response) { function processResponse(response){
var data = []; var data = [];
/* /*
* History data is organised by Sol. Iterate over sols... * History data is organised by Sol. Iterate over sols...
*/ */
response.data.soles.forEach(function (solData) { response.data.soles.forEach(function(solData){
/* /*
* Check that valid data exists * Check that valid data exists
*/ */
@ -106,13 +106,13 @@ define(
//Filter results to match request parameters //Filter results to match request parameters
function filterResults(results) { function filterResults(results) {
return results.filter(function (result) { return results.filter(function(result){
return result.date >= (request.start || Number.MIN_VALUE) && return result.date >= (request.start || Number.MIN_VALUE) &&
result.date <= (request.end || Number.MAX_VALUE); result.date <= (request.end || Number.MAX_VALUE);
}); });
} }
function packageAndResolve(results) { function packageAndResolve(results){
return {id: id, values: results}; return {id: id, values: results};
} }
@ -132,7 +132,7 @@ define(
* @param id The telemetry data point key to be queried. * @param id The telemetry data point key to be queried.
* @returns {Promise | Array<RemsTelemetryValue>} that resolves with an Array of {@link RemsTelemetryValue} objects for the request data key. * @returns {Promise | Array<RemsTelemetryValue>} that resolves with an Array of {@link RemsTelemetryValue} objects for the request data key.
*/ */
RemsTelemetryServerAdapter.prototype.history = function (request) { RemsTelemetryServerAdapter.prototype.history = function(request) {
return this.requestHistory(request); return this.requestHistory(request);
}; };

View File

@ -27,20 +27,20 @@ define([
"./src/DialogLaunchIndicator", "./src/DialogLaunchIndicator",
"./src/NotificationLaunchIndicator", "./src/NotificationLaunchIndicator",
"./res/dialog-launch.html", "./res/dialog-launch.html",
"./res/notification-launch.html" "./res/notification-launch.html",
'legacyRegistry'
], function ( ], function (
DialogLaunchController, DialogLaunchController,
NotificationLaunchController, NotificationLaunchController,
DialogLaunchIndicator, DialogLaunchIndicator,
NotificationLaunchIndicator, NotificationLaunchIndicator,
DialogLaunch, DialogLaunch,
NotificationLaunch NotificationLaunch,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/notifications", {
name:"example/notifications",
definition: {
"extensions": { "extensions": {
"templates": [ "templates": [
{ {
@ -86,6 +86,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -1,9 +1,9 @@
<span class="h-indicator" ng-controller="DialogLaunchController"> <span class="h-indicator" ng-controller="DialogLaunchController">
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! --> <!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<div class="c-indicator c-indicator--clickable icon-box-with-arrow s-status-available"><span class="label c-indicator__label"> <div class="c-indicator c-indicator--clickable icon-box-with-arrow s-status-available"><span class="label">
<button ng-click="launchProgress(true)">Known</button> <a ng-click="launchProgress(true)">Known</a>
<button ng-click="launchProgress(false)">Unknown</button> <a ng-click="launchProgress(false)">Unknown</a>
<button ng-click="launchError()">Error</button> <a ng-click="launchError()">Error</a>
<button ng-click="launchInfo()">Info</button> <a ng-click="launchInfo()">Info</a>
</span></div> </span></div>
</span> </span>

View File

@ -1,9 +1,9 @@
<span class="h-indicator" ng-controller="NotificationLaunchController"> <span class="h-indicator" ng-controller="NotificationLaunchController">
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! --> <!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<div class="c-indicator c-indicator--clickable icon-bell s-status-available"><span class="label c-indicator__label"> <div class="c-indicator c-indicator--clickable icon-bell s-status-available"><span class="label">
<button ng-click="newInfo()">Success</button> <a ng-click="newInfo()">Success</a>
<button ng-click="newError()">Error</button> <a ng-click="newError()">Error</a>
<button ng-click="newAlert()">Alert</button> <a ng-click="newAlert()">Alert</a>
<button ng-click="newProgress()">Progress</button> <a ng-click="newProgress()">Progress</a>
</span></div> </span></div>
</span> </span>

View File

@ -22,15 +22,15 @@
/*global define*/ /*global define*/
define([ define([
"./src/BrowserPersistenceProvider" "./src/BrowserPersistenceProvider",
'legacyRegistry'
], function ( ], function (
BrowserPersistenceProvider BrowserPersistenceProvider,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/persistence", {
name:"example/persistence",
definition: {
"extensions": { "extensions": {
"components": [ "components": [
{ {
@ -50,6 +50,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -22,15 +22,15 @@
/*global define*/ /*global define*/
define([ define([
"./src/ExamplePolicy" "./src/ExamplePolicy",
'legacyRegistry'
], function ( ], function (
ExamplePolicy ExamplePolicy,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/policy", {
name:"example/policy",
definition: {
"name": "Example Policy", "name": "Example Policy",
"description": "Provides an example of using policies to prohibit actions.", "description": "Provides an example of using policies to prohibit actions.",
"extensions": { "extensions": {
@ -41,6 +41,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -23,16 +23,16 @@
define([ define([
"./src/WatchIndicator", "./src/WatchIndicator",
"./src/DigestIndicator" "./src/DigestIndicator",
'legacyRegistry'
], function ( ], function (
WatchIndicator, WatchIndicator,
DigestIndicator DigestIndicator,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/profiling", {
name:"example/profiling",
definition: {
"extensions": { "extensions": {
"indicators": [ "indicators": [
{ {
@ -51,6 +51,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -22,15 +22,15 @@
/*global define*/ /*global define*/
define([ define([
"./src/ScratchPersistenceProvider" "./src/ScratchPersistenceProvider",
'legacyRegistry'
], function ( ], function (
ScratchPersistenceProvider ScratchPersistenceProvider,
legacyRegistry
) { ) {
"use strict"; "use strict";
return { legacyRegistry.register("example/scratchpad", {
name:"example/scratchpad",
definition: {
"extensions": { "extensions": {
"roots": [ "roots": [
{ {
@ -59,6 +59,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -1,10 +1,10 @@
<template> <template>
<div class="example">{{ msg }}</div> <div class="example">{{ msg }}</div>
</template> </template>
<script> <script>
export default { export default {
data() { data () {
return { return {
msg: 'Hello world!' msg: 'Hello world!'
} }

View File

@ -1,8 +1,10 @@
import Vue from 'Vue'; import Vue from 'Vue';
import HelloWorld from './HelloWorld.vue'; import HelloWorld from './HelloWorld.vue';
function SimpleVuePlugin() { function SimpleVuePlugin () {
return function install(openmct) { return function install(openmct) {
var views = (openmct.mainViews || openmct.objectViews);
openmct.types.addType('hello-world', { openmct.types.addType('hello-world', {
name: 'Hello World', name: 'Hello World',
description: 'An introduction object', description: 'An introduction object',

View File

@ -8,7 +8,8 @@ define([
"./res/templates/glyphs.html", "./res/templates/glyphs.html",
"./res/templates/controls.html", "./res/templates/controls.html",
"./res/templates/input.html", "./res/templates/input.html",
"./res/templates/menus.html" "./res/templates/menus.html",
'legacyRegistry'
], function ( ], function (
ExampleStyleGuideModelProvider, ExampleStyleGuideModelProvider,
MCTExample, MCTExample,
@ -19,11 +20,10 @@ define([
glyphsTemplate, glyphsTemplate,
controlsTemplate, controlsTemplate,
inputTemplate, inputTemplate,
menusTemplate menusTemplate,
legacyRegistry
) { ) {
return { legacyRegistry.register("example/styleguide", {
name:"example/styleguide",
definition: {
"name": "Open MCT Style Guide", "name": "Open MCT Style Guide",
"description": "Examples and documentation illustrating UI styles in use in Open MCT.", "description": "Examples and documentation illustrating UI styles in use in Open MCT.",
"extensions": "extensions":
@ -103,6 +103,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -30,14 +30,14 @@ define(
var pages = {}; var pages = {};
// Add pages // Add pages
pages.intro = { name: "Introduction", type: "styleguide.intro", location: "styleguide:home" }; pages['intro'] = { name: "Introduction", type: "styleguide.intro", location: "styleguide:home" };
pages.standards = { name: "Standards", type: "styleguide.standards", location: "styleguide:home" }; pages['standards'] = { name: "Standards", type: "styleguide.standards", location: "styleguide:home" };
pages.colors = { name: "Colors", type: "styleguide.colors", location: "styleguide:home" }; pages['colors'] = { name: "Colors", type: "styleguide.colors", location: "styleguide:home" };
pages.glyphs = { name: "Glyphs", type: "styleguide.glyphs", location: "styleguide:home" }; pages['glyphs'] = { name: "Glyphs", type: "styleguide.glyphs", location: "styleguide:home" };
pages.status = { name: "Status Indication", type: "styleguide.status", location: "styleguide:home" }; pages['status'] = { name: "Status Indication", type: "styleguide.status", location: "styleguide:home" };
pages.controls = { name: "Controls", type: "styleguide.controls", location: "styleguide:ui-elements" }; pages['controls'] = { name: "Controls", type: "styleguide.controls", location: "styleguide:ui-elements" };
pages.input = { name: "Text Inputs", type: "styleguide.input", location: "styleguide:ui-elements" }; pages['input'] = { name: "Text Inputs", type: "styleguide.input", location: "styleguide:ui-elements" };
pages.menus = { name: "Menus", type: "styleguide.menus", location: "styleguide:ui-elements" }; pages['menus'] = { name: "Menus", type: "styleguide.menus", location: "styleguide:ui-elements" };
return { return {
getModels: function () { getModels: function () {

View File

@ -1,5 +1,5 @@
<!-- <!--
Open MCT, Copyright (c) 2014-2020, United States Government Open MCT, Copyright (c) 2014-2017, United States Government
as represented by the Administrator of the National Aeronautics and Space as represented by the Administrator of the National Aeronautics and Space
Administration. All rights reserved. Administration. All rights reserved.
@ -27,9 +27,11 @@
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<title></title> <title></title>
<script src="dist/openmct.js"></script> <script src="dist/openmct.js"></script>
<link rel="icon" type="image/png" href="dist/favicons/favicon-96x96.png" sizes="96x96" type="image/x-icon"> <link rel="stylesheet" href="dist/styles/openmct.css">
<link rel="icon" type="image/png" href="dist/favicons/favicon-32x32.png" sizes="32x32" type="image/x-icon"> <link rel="icon" type="image/png" href="dist/favicons/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="dist/favicons/favicon-16x16.png" sizes="16x16" type="image/x-icon"> <link rel="icon" type="image/png" href="dist/favicons/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="dist/favicons/favicon-16x16.png" sizes="16x16">
<link rel="shortcut icon" href="dist/favicons/favicon.ico">
</head> </head>
<body> <body>
</body> </body>
@ -38,17 +40,17 @@
const THIRTY_MINUTES = 30 * 60 * 1000; const THIRTY_MINUTES = 30 * 60 * 1000;
[ [
'example/eventGenerator' 'example/eventGenerator',
'example/styleguide'
].forEach( ].forEach(
openmct.legacyRegistry.enable.bind(openmct.legacyRegistry) openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
); );
openmct.install(openmct.plugins.LocalStorage());
openmct.install(openmct.plugins.Espresso());
openmct.install(openmct.plugins.MyItems()); openmct.install(openmct.plugins.MyItems());
openmct.install(openmct.plugins.LocalStorage());
openmct.install(openmct.plugins.Generator()); openmct.install(openmct.plugins.Generator());
openmct.install(openmct.plugins.ExampleImagery()); openmct.install(openmct.plugins.ExampleImagery());
openmct.install(openmct.plugins.UTCTimeSystem()); openmct.install(openmct.plugins.UTCTimeSystem());
openmct.install(openmct.plugins.ImportExport());
openmct.install(openmct.plugins.AutoflowView({ openmct.install(openmct.plugins.AutoflowView({
type: "telemetry.panel" type: "telemetry.panel"
})); }));
@ -78,10 +80,14 @@
})); }));
openmct.install(openmct.plugins.SummaryWidget()); openmct.install(openmct.plugins.SummaryWidget());
openmct.install(openmct.plugins.Notebook()); openmct.install(openmct.plugins.Notebook());
openmct.install(openmct.plugins.FolderView());
openmct.install(openmct.plugins.Tabs());
openmct.install(openmct.plugins.FlexibleLayout());
openmct.install(openmct.plugins.LADTable()); openmct.install(openmct.plugins.LADTable());
openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay'])); openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
openmct.install(openmct.plugins.ObjectMigration()); openmct.install(openmct.plugins.ObjectMigration());
openmct.install(openmct.plugins.ClearData(['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'])); openmct.install(openmct.plugins.GoToOriginalAction());
openmct.install(openmct.plugins.GlobalClearIndicator());
openmct.start(); openmct.start();
</script> </script>
</html> </html>

View File

@ -23,28 +23,17 @@
/*global module,process*/ /*global module,process*/
const devMode = process.env.NODE_ENV !== 'production'; const devMode = process.env.NODE_ENV !== 'production';
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless'];
const coverageEnabled = process.env.COVERAGE === 'true';
const reporters = ['progress', 'html'];
if (coverageEnabled) {
reporters.push('coverage-istanbul');
}
module.exports = (config) => { module.exports = (config) => {
const webpackConfig = require('./webpack.config.js'); const webpackConfig = require('./webpack.config.js');
delete webpackConfig.output; delete webpackConfig.output;
if (!devMode || coverageEnabled) { if (!devMode) {
webpackConfig.module.rules.push({ webpackConfig.module.rules.push({
test: /\.js$/, test: /\.js$/,
exclude: /node_modules|example|lib|dist/, exclude: /node_modules|example/,
use: { use: 'istanbul-instrumenter-loader'
loader: 'istanbul-instrumenter-loader',
options: {
esModules: true
}
}
}); });
} }
@ -56,41 +45,43 @@ module.exports = (config) => {
'src/**/*Spec.js' 'src/**/*Spec.js'
], ],
port: 9876, port: 9876,
reporters: reporters, reporters: [
browsers: browsers, 'progress',
customLaunchers: { 'coverage',
ChromeDebugging: { 'html'
base: 'Chrome', ],
flags: ['--remote-debugging-port=9222'], browsers: ['ChromeHeadless'],
debug: true
}
},
colors: true, colors: true,
logLevel: config.LOG_INFO, logLevel: config.LOG_INFO,
autoWatch: true, autoWatch: true,
coverageReporter: {
dir: process.env.CIRCLE_ARTIFACTS ?
process.env.CIRCLE_ARTIFACTS + '/coverage' :
"dist/reports/coverage",
check: {
global: {
lines: 80,
excludes: ['src/plugins/plot/**/*.js']
}
}
},
// HTML test reporting. // HTML test reporting.
htmlReporter: { htmlReporter: {
outputDir: "dist/reports/tests", outputDir: "dist/reports/tests",
preserveDescribeNesting: true, preserveDescribeNesting: true,
foldAll: false foldAll: false
}, },
coverageIstanbulReporter: {
fixWebpackSourcePaths: true,
dir: process.env.CIRCLE_ARTIFACTS ?
process.env.CIRCLE_ARTIFACTS + '/coverage' :
"dist/reports/coverage",
reports: ['html', 'lcovonly', 'text-summary'],
thresholds: {
global: {
lines: 62
}
}
},
preprocessors: { preprocessors: {
'platform/**/*Spec.js': ['webpack', 'sourcemap'], // add webpack as preprocessor
'src/**/*Spec.js': ['webpack', 'sourcemap'] 'platform/**/*Spec.js': [ 'webpack' ],
'src/**/*Spec.js': [ 'webpack' ]
}, },
webpack: webpackConfig, webpack: webpackConfig,
webpackMiddleware: { webpackMiddleware: {
stats: 'errors-only', stats: 'errors-only',
logLevel: 'warn' logLevel: 'warn'
@ -98,3 +89,4 @@ module.exports = (config) => {
singleRun: true singleRun: true
}); });
} }

View File

@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available * this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
/*global module*/ /*global module,BUILD_CONSTANTS*/
const matcher = /\/openmct.js$/; const matcher = /\/openmct.js$/;
if (document.currentScript) { if (document.currentScript) {

View File

@ -1,16 +1,15 @@
{ {
"name": "openmct", "name": "openmct",
"version": "1.0.0-snapshot", "version": "0.14.0-SNAPSHOT",
"description": "The Open MCT core platform", "description": "The Open MCT core platform",
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"angular": ">=1.8.0", "angular": "1.4.14",
"angular-route": "1.4.14", "angular-route": "1.4.14",
"babel-eslint": "8.2.6", "babel-eslint": "8.2.6",
"comma-separated-values": "^3.6.4", "comma-separated-values": "^3.6.4",
"concurrently": "^3.6.1", "concurrently": "^3.6.1",
"copy-webpack-plugin": "^4.5.2", "copy-webpack-plugin": "^4.5.2",
"cross-env": "^6.0.3",
"css-loader": "^1.0.0", "css-loader": "^1.0.0",
"d3-array": "1.2.x", "d3-array": "1.2.x",
"d3-axis": "1.0.x", "d3-axis": "1.0.x",
@ -23,8 +22,6 @@
"d3-time": "1.0.x", "d3-time": "1.0.x",
"d3-time-format": "2.1.x", "d3-time-format": "2.1.x",
"eslint": "5.2.0", "eslint": "5.2.0",
"eslint-plugin-vue": "^6.0.0",
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0",
"eventemitter3": "^1.2.0", "eventemitter3": "^1.2.0",
"exports-loader": "^0.7.0", "exports-loader": "^0.7.0",
"express": "^4.13.1", "express": "^4.13.1",
@ -43,29 +40,26 @@
"karma-chrome-launcher": "^2.2.0", "karma-chrome-launcher": "^2.2.0",
"karma-cli": "^1.0.1", "karma-cli": "^1.0.1",
"karma-coverage": "^1.1.2", "karma-coverage": "^1.1.2",
"karma-coverage-istanbul-reporter": "^2.1.1",
"karma-html-reporter": "^0.2.7", "karma-html-reporter": "^0.2.7",
"karma-jasmine": "^1.1.2", "karma-jasmine": "^1.1.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^3.0.0", "karma-webpack": "^3.0.0",
"location-bar": "^3.0.1", "location-bar": "^3.0.1",
"lodash": "^4.17.12", "lodash": "^3.10.1",
"markdown-toc": "^0.11.7", "markdown-toc": "^0.11.7",
"marked": "^0.3.5", "marked": "^0.3.5",
"mini-css-extract-plugin": "^0.4.1", "mini-css-extract-plugin": "^0.4.1",
"minimist": "^1.1.1", "minimist": "^1.1.1",
"moment": "2.25.3", "moment": "^2.11.1",
"moment-duration-format": "^2.2.2", "moment-duration-format": "^2.2.2",
"moment-timezone": "0.5.28", "moment-timezone": "^0.5.21",
"node-bourbon": "^4.2.3", "node-bourbon": "^4.2.3",
"node-sass": "^4.9.2", "node-sass": "^4.9.2",
"painterro": "^0.2.65", "painterro": "^0.2.65",
"printj": "^1.2.1", "printj": "^1.1.0",
"raw-loader": "^0.5.1", "raw-loader": "^0.5.1",
"request": "^2.69.0", "request": "^2.69.0",
"split": "^1.0.0", "split": "^1.0.0",
"style-loader": "^1.0.1", "style-loader": "^0.21.0",
"uuid": "^3.3.3",
"v8-compile-cache": "^1.1.0", "v8-compile-cache": "^1.1.0",
"vue": "2.5.6", "vue": "2.5.6",
"vue-loader": "^15.2.6", "vue-loader": "^15.2.6",
@ -77,17 +71,14 @@
"zepto": "^1.2.0" "zepto": "^1.2.0"
}, },
"scripts": { "scripts": {
"clean": "rm -rf ./dist",
"start": "node app.js", "start": "node app.js",
"lint": "eslint platform example src --ext .js,.vue openmct.js", "lint": "eslint platform src openmct.js",
"lint:fix": "eslint platform example src --ext .js,.vue openmct.js --fix", "lint:fix": "eslint platform src openmct.js --fix",
"build:prod": "cross-env NODE_ENV=production webpack", "build:prod": "NODE_ENV=production webpack",
"build:dev": "webpack", "build:dev": "webpack",
"build:watch": "webpack --watch", "build:watch": "webpack --watch",
"test": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run", "test": "karma start --single-run",
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run", "test:watch": "karma start --no-single-run",
"test:coverage": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" COVERAGE=true karma start --single-run",
"test:watch": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --no-single-run",
"verify": "concurrently 'npm:test' 'npm:lint'", "verify": "concurrently 'npm:test' 'npm:lint'",
"jsdoc": "jsdoc -c jsdoc.json -R API.md -r -d dist/docs/api", "jsdoc": "jsdoc -c jsdoc.json -R API.md -r -d dist/docs/api",
"otherdoc": "node docs/gendocs.js --in docs/src --out dist/docs --suppress-toc 'docs/src/index.md|docs/src/process/index.md'", "otherdoc": "node docs/gendocs.js --in docs/src --out dist/docs --suppress-toc 'docs/src/index.md|docs/src/process/index.md'",

View File

@ -31,7 +31,8 @@ define([
"./res/templates/license-apache.html", "./res/templates/license-apache.html",
"./res/templates/license-mit.html", "./res/templates/license-mit.html",
"./res/templates/licenses.html", "./res/templates/licenses.html",
"./res/templates/licenses-export-md.html" "./res/templates/licenses-export-md.html",
'legacyRegistry'
], function ( ], function (
aboutDialogTemplate, aboutDialogTemplate,
LogoController, LogoController,
@ -43,12 +44,11 @@ define([
licenseApacheTemplate, licenseApacheTemplate,
licenseMitTemplate, licenseMitTemplate,
licensesTemplate, licensesTemplate,
licensesExportMdTemplate licensesExportMdTemplate,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/about", {
name:"platform/commonUI/about",
definition: {
"name": "About Open MCT", "name": "About Open MCT",
"extensions": { "extensions": {
"templates": [ "templates": [
@ -176,6 +176,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -21,6 +21,12 @@
*****************************************************************************/ *****************************************************************************/
define([ define([
"./src/BrowseController",
"./src/PaneController",
"./src/InspectorPaneController",
"./src/BrowseObjectController",
"./src/MenuArrowController",
"./src/ObjectHeaderController",
"./src/navigation/NavigationService", "./src/navigation/NavigationService",
"./src/navigation/NavigateAction", "./src/navigation/NavigateAction",
"./src/navigation/OrphanNavigationHandler", "./src/navigation/OrphanNavigationHandler",
@ -32,8 +38,15 @@ define([
"./res/templates/menu-arrow.html", "./res/templates/menu-arrow.html",
"./res/templates/back-arrow.html", "./res/templates/back-arrow.html",
"./res/templates/browse/object-properties.html", "./res/templates/browse/object-properties.html",
"./res/templates/browse/inspector-region.html" "./res/templates/browse/inspector-region.html",
'legacyRegistry'
], function ( ], function (
BrowseController,
PaneController,
InspectorPaneController,
BrowseObjectController,
MenuArrowController,
ObjectHeaderController,
NavigationService, NavigationService,
NavigateAction, NavigateAction,
OrphanNavigationHandler, OrphanNavigationHandler,
@ -45,12 +58,11 @@ define([
menuArrowTemplate, menuArrowTemplate,
backArrowTemplate, backArrowTemplate,
objectPropertiesTemplate, objectPropertiesTemplate,
inspectorRegionTemplate inspectorRegionTemplate,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/browse", {
name:"platform/commonUI/browse",
definition: {
"extensions": { "extensions": {
"routes": [ "routes": [
], ],
@ -61,6 +73,70 @@ define([
"priority": "fallback" "priority": "fallback"
} }
], ],
"controllers": [
{
"key": "BrowseController",
"implementation": BrowseController,
"depends": [
"$scope",
"$route",
"$location",
"objectService",
"navigationService",
"urlService",
"DEFAULT_PATH"
]
},
{
"key": "PaneController",
"implementation": PaneController,
"priority": "preferred",
"depends": [
"$scope",
"agentService",
"$window",
"$location",
"$attrs",
"navigationService"
]
},
{
"key": "BrowseObjectController",
"implementation": BrowseObjectController,
"depends": [
"$scope",
"$location",
"$route"
]
},
{
"key": "MenuArrowController",
"implementation": MenuArrowController,
"depends": [
"$scope"
]
},
{
"key": "InspectorPaneController",
"implementation": InspectorPaneController,
"priority": "preferred",
"depends": [
"$scope",
"agentService",
"$window",
"navigationService",
"$location",
"$attrs"
]
},
{
"key": "ObjectHeaderController",
"implementation": ObjectHeaderController,
"depends": [
"$scope"
]
}
],
"representations": [ "representations": [
{ {
"key": "browse-object", "key": "browse-object",
@ -172,6 +248,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -0,0 +1,215 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* This bundle implements Browse mode.
* @namespace platform/commonUI/browse
*/
define(
['lodash'],
function (_) {
/**
* The BrowseController is used to populate the initial scope in Browse
* mode. It loads the root object from the objectService and makes it
* available in the scope for Angular template's; this is the point at
* which Angular templates first have access to the domain object
* hierarchy.
*
* @memberof platform/commonUI/browse
* @constructor
*/
function BrowseController(
$scope,
$route,
$location,
objectService,
navigationService,
urlService,
defaultPath
) {
window.browseScope = $scope;
var initialPath = ($route.current.params.ids || defaultPath).split("/"),
currentIds;
$scope.treeModel = {
selectedObject: undefined,
onSelection: function (object) {
navigationService.setNavigation(object, true);
},
allowSelection: function (object) {
var domainObjectInView = navigationService.getNavigation(),
isInEditMode = domainObjectInView.getCapability('status').get('editing');
if (isInEditMode) {
var actions = object.getCapability('action'),
previewAction = actions.getActions({key: 'mct-preview-action'})[0];
if (previewAction && previewAction.perform) {
previewAction.perform();
return false;
} else {
return navigationService.shouldNavigate();
}
} else {
return true;
}
}
};
function idsForObject(domainObject) {
return urlService
.urlForLocation("", domainObject)
.replace('/', '');
}
// Find an object in an array of objects.
function findObject(domainObjects, id) {
var i;
for (i = 0; i < domainObjects.length; i += 1) {
if (domainObjects[i].getId() === id) {
return domainObjects[i];
}
}
}
// helper, fetch a single object from the object service.
function getObject(id) {
return objectService.getObjects([id])
.then(function (results) {
return results[id];
});
}
// recursively locate and return an object inside of a container
// via a path. If at any point in the recursion it fails to find
// the next object, it will return the parent.
function findViaComposition(containerObject, path) {
var nextId = path.shift();
if (!nextId) {
return containerObject;
}
return containerObject.useCapability('composition')
.then(function (composees) {
var nextObject = findObject(composees, nextId);
if (!nextObject) {
return containerObject;
}
if (!nextObject.hasCapability('composition')) {
return nextObject;
}
return findViaComposition(nextObject, path);
});
}
function navigateToObject(desiredObject) {
$scope.navigatedObject = desiredObject;
$scope.treeModel.selectedObject = desiredObject;
currentIds = idsForObject(desiredObject);
$route.current.pathParams.ids = currentIds;
$location.path('/browse/' + currentIds);
}
function getLastChildIfRoot(object) {
if (object.getId() !== 'ROOT') {
return object;
}
return object.useCapability('composition')
.then(function (composees) {
return composees[composees.length - 1];
});
}
function navigateToPath(path) {
return getObject('ROOT')
.then(function (root) {
return findViaComposition(root, path);
})
.then(getLastChildIfRoot)
.then(function (object) {
navigationService.setNavigation(object);
});
}
getObject('ROOT')
.then(function (root) {
$scope.domainObject = root;
navigateToPath(initialPath);
});
// Handle navigation events from view service. Only navigates
// if path has changed.
function navigateDirectlyToModel(domainObject) {
var newIds = idsForObject(domainObject);
if (currentIds !== newIds) {
currentIds = newIds;
navigateToObject(domainObject);
}
}
// Listen for changes in navigation state.
navigationService.addListener(navigateDirectlyToModel);
// Listen for route changes which are caused by browser events
// (e.g. bookmarks to pages in OpenMCT) and prevent them. Instead,
// navigate to the path ourselves, which results in it being
// properly set.
$scope.$on('$routeChangeStart', function (event, route, oldRoute) {
if (route.$$route === $route.current.$$route) {
if (route.pathParams.ids &&
route.pathParams.ids !== $route.current.pathParams.ids) {
var otherParams = _.omit(route.params, 'ids');
var oldOtherParams = _.omit(oldRoute.params, 'ids');
var deletedParams = _.omit(oldOtherParams, _.keys(otherParams));
event.preventDefault();
navigateToPath(route.pathParams.ids.split('/'))
.then(function () {
if (!_.isEqual(otherParams, oldOtherParams)) {
_.forEach(otherParams, function (v, k) {
$location.search(k, v);
});
_.forEach(deletedParams, function (k) {
$location.search(k, null);
});
}
});
} else {
navigateToPath([]);
}
}
});
// Clean up when the scope is destroyed
$scope.$on("$destroy", function () {
navigationService.removeListener(navigateDirectlyToModel);
});
}
return BrowseController;
}
);

View File

@ -0,0 +1,72 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[],
function () {
/**
* Controller for the `browse-object` representation of a domain
* object (the right-hand side of Browse mode.)
* @memberof platform/commonUI/browse
* @constructor
*/
function BrowseObjectController($scope, $location, $route) {
function setViewForDomainObject(domainObject) {
var locationViewKey = $location.search().view;
function selectViewIfMatching(view) {
if (view.key === locationViewKey) {
$scope.representation = $scope.representation || {};
$scope.representation.selected = view;
}
}
if (locationViewKey) {
((domainObject && domainObject.useCapability('view')) || [])
.forEach(selectViewIfMatching);
}
}
function updateQueryParam(viewKey) {
if (viewKey && $location.search().view !== viewKey) {
$location.search('view', viewKey);
}
}
$scope.$watch('domainObject', setViewForDomainObject);
$scope.$watch('representation.selected.key', updateQueryParam);
$scope.$on('$locationChangeSuccess', function () {
setViewForDomainObject($scope.domainObject);
});
$scope.doAction = function (action) {
return $scope[action] && $scope[action]();
};
}
return BrowseObjectController;
}
);

View File

@ -0,0 +1,78 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
["./PaneController"],
function (PaneController) {
/**
* Pane controller that reveals inspector, if hidden, when object
* switches to edit mode.
*
* @param $scope
* @param agentService
* @param $window
* @param navigationService
* @constructor
*/
function InspectorPaneController($scope, agentService, $window, navigationService, $location, $attrs) {
PaneController.call(this, $scope, agentService, $window, $location, $attrs);
var statusListener,
self = this;
function showInspector(statuses) {
if (statuses.indexOf('editing') !== -1 && !self.visible()) {
self.toggle();
}
}
function attachStatusListener(domainObject) {
// Remove existing status listener if existing
if (statusListener) {
statusListener();
}
if (domainObject.hasCapability("status")) {
statusListener = domainObject.getCapability("status").listen(showInspector);
}
return statusListener;
}
var domainObject = navigationService.getNavigation();
if (domainObject) {
attachStatusListener(domainObject);
}
navigationService.addListener(attachStatusListener);
$scope.$on("$destroy", function () {
statusListener();
navigationService.removeListener(attachStatusListener);
});
}
InspectorPaneController.prototype = Object.create(PaneController.prototype);
return InspectorPaneController;
}
);

View File

@ -1,5 +1,5 @@
/***************************************************************************** /*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, United States Government * Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space * as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved. * Administration. All rights reserved.
* *
@ -19,50 +19,41 @@
* this source code distribution or the Licensing information page available * this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
import { TRIGGER } from "./constants";
export const evaluateResults = (results, trigger) => { /**
if (trigger && trigger === TRIGGER.XOR) { * Module defining MenuArrowController. Created by shale on 06/30/2015.
return matchExact(results, 1); */
} else if (trigger && trigger === TRIGGER.NOT) { define(
return matchExact(results, 0); [],
} else if (trigger && trigger === TRIGGER.ALL) { function () {
return matchAll(results);
} else {
return matchAny(results);
}
}
function matchAll(results) { /**
for (const result of results) { * A left-click on the menu arrow should display a
if (result !== true) { * context menu. This controller launches the context
return false; * menu.
} * @memberof platform/commonUI/browse
* @constructor
*/
function MenuArrowController($scope) {
this.$scope = $scope;
} }
return true; /**
} * Show a context menu for the domain object in this scope.
*
* @param event the browser event which caused this (used to
* position the menu)
*/
MenuArrowController.prototype.showMenu = function (event) {
var actionContext = {
key: 'menu',
domainObject: this.$scope.domainObject,
event: event
};
function matchAny(results) { this.$scope.domainObject.getCapability('action').perform(actionContext);
for (const result of results) { };
if (result === true) {
return true;
}
}
return false; return MenuArrowController;
}
function matchExact(results, target) {
let matches = 0;
for (const result of results) {
if (result === true) {
matches++;
} }
if (matches > target) { );
return false;
}
}
return matches === target;
}

View File

@ -0,0 +1,92 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[],
function () {
/**
* Controller to provide the ability to inline edit an object name.
*
* @constructor
* @memberof platform/commonUI/browse
*/
function ObjectHeaderController($scope) {
this.$scope = $scope;
this.domainObject = $scope.domainObject;
this.editable = this.allowEdit();
}
/**
* Updates the object name on blur and enter keypress events.
*
* @param event the mouse event
*/
ObjectHeaderController.prototype.updateName = function (event) {
if (!event || !event.currentTarget) {
return;
}
if (event.type === 'blur') {
this.updateModel(event);
} else if (event.which === 13) {
this.updateModel(event);
event.currentTarget.blur();
window.getSelection().removeAllRanges();
}
};
/**
* Updates the model.
*
* @param event the mouse event
* @param private
*/
ObjectHeaderController.prototype.updateModel = function (event) {
var name = event.currentTarget.textContent.replace(/\n/g, ' ');
if (name.length === 0) {
name = "Unnamed " + this.domainObject.getCapability("type").typeDef.name;
event.currentTarget.textContent = name;
}
if (name !== this.domainObject.getModel().name) {
this.domainObject.getCapability('mutation').mutate(function (model) {
model.name = name;
});
}
};
/**
* Checks if the domain object is editable.
*
* @private
* @return true if object is editable
*/
ObjectHeaderController.prototype.allowEdit = function () {
var type = this.domainObject && this.domainObject.getCapability('type');
return !!(type && type.hasFeature('creation'));
};
return ObjectHeaderController;
}
);

View File

@ -0,0 +1,88 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[],
function () {
var navigationListenerAdded = false;
/**
* Controller to provide the ability to show/hide the tree in
* Browse mode.
* @constructor
* @memberof platform/commonUI/browse
*/
function PaneController($scope, agentService, $window, $location, $attrs, navigationService) {
var self = this;
this.agentService = agentService;
var hideParameterPresent = $location.search().hasOwnProperty($attrs.hideParameter);
if ($attrs.hideParameter && hideParameterPresent) {
this.state = false;
$location.search($attrs.hideParameter, undefined);
} else {
this.state = true;
}
/**
* Callback to invoke when any selection occurs in the tree.
* This controller can be passed in as the `parameters` object
* to the tree representation.
*
* @property {Function} callback
* @memberof platform/commonUI/browse.PaneController#
*/
this.callback = function () {
// Note that, since this is a callback to pass, this is not
// declared as a method but as a property which happens to
// be a function.
if (agentService.isPhone() && agentService.isPortrait()) {
// On phones, trees should collapse in portrait mode
// when something is navigated-to.
self.state = false;
}
};
if (navigationService && navigationService.addListener && !navigationListenerAdded) {
navigationService.addListener(this.callback);
navigationListenerAdded = true;
}
}
/**
* Toggle the visibility of the pane.
*/
PaneController.prototype.toggle = function () {
this.state = !this.state;
};
/**
* Get the desired visibility state of the pane.
* @returns {boolean} true when visible
*/
PaneController.prototype.visible = function () {
return !!this.state;
};
return PaneController;
}
);

View File

@ -0,0 +1,266 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global console*/
/**
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
*/
define(
[
"../src/BrowseController",
"../src/navigation/NavigationService"
],
function (
BrowseController,
NavigationService
) {
describe("The browse controller", function () {
var mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService,
mockRootObject,
mockUrlService,
mockDefaultRootObject,
mockOtherDomainObject,
mockNextObject,
testDefaultRoot,
controller;
function waitsForNavigation() {
return new Promise(function (resolve) {
mockNavigationService.setNavigation.and.callFake(function (obj) {
var returnValue;
try {
returnValue = NavigationService.prototype.setNavigation.call(mockNavigationService, obj);
} catch (err) {
console.error(err);
//Not rejecting because 'setNavigation' has been called, which is what's being tested here.
//Rejecting will fail tests.
}
resolve();
return returnValue;
});
});
}
function instantiateController() {
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService,
mockUrlService,
testDefaultRoot
);
}
beforeEach(function () {
testDefaultRoot = "some-root-level-domain-object";
mockScope = jasmine.createSpyObj(
"$scope",
["$on", "$watch"]
);
mockRoute = { current: { params: {}, pathParams: {} } };
mockUrlService = jasmine.createSpyObj(
"urlService",
["urlForLocation"]
);
mockUrlService.urlForLocation.and.callFake(function (mode, object) {
if (object === mockDefaultRootObject) {
return [mode, testDefaultRoot].join('/');
}
if (object === mockOtherDomainObject) {
return [mode, 'other'].join('/');
}
if (object === mockNextObject) {
return [mode, testDefaultRoot, 'next'].join('/');
}
throw new Error('Tried to get url for unexpected object');
});
mockLocation = jasmine.createSpyObj(
"$location",
["path"]
);
mockObjectService = jasmine.createSpyObj(
"objectService",
["getObjects"]
);
mockNavigationService = new NavigationService({});
[
"getNavigation",
"setNavigation",
"addListener",
"removeListener"
].forEach(function (method) {
spyOn(mockNavigationService, method)
.and.callThrough();
});
mockRootObject = jasmine.createSpyObj(
"rootObjectContainer",
["getId", "getCapability", "getModel", "useCapability", "hasCapability"]
);
mockDefaultRootObject = jasmine.createSpyObj(
"defaultRootObject",
["getId", "getCapability", "getModel", "useCapability", "hasCapability"]
);
mockOtherDomainObject = jasmine.createSpyObj(
"otherDomainObject",
["getId", "getCapability", "getModel", "useCapability", "hasCapability"]
);
mockNextObject = jasmine.createSpyObj(
"nestedDomainObject",
["getId", "getCapability", "getModel", "useCapability", "hasCapability"]
);
mockObjectService.getObjects.and.returnValue(Promise.resolve({
ROOT: mockRootObject
}));
mockRootObject.useCapability.and.returnValue(Promise.resolve([
mockOtherDomainObject,
mockDefaultRootObject
]));
mockRootObject.hasCapability.and.returnValue(true);
mockDefaultRootObject.useCapability.and.returnValue(Promise.resolve([
mockNextObject
]));
mockDefaultRootObject.hasCapability.and.returnValue(true);
mockOtherDomainObject.hasCapability.and.returnValue(false);
mockNextObject.useCapability.and.returnValue(undefined);
mockNextObject.hasCapability.and.returnValue(false);
mockNextObject.getId.and.returnValue("next");
mockDefaultRootObject.getId.and.returnValue(testDefaultRoot);
instantiateController();
return waitsForNavigation();
});
it("uses composition to set the navigated object, if there is none", function () {
instantiateController();
return waitsForNavigation().then(function () {
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
it("navigates to a root-level object, even when default path is not found", function () {
mockDefaultRootObject.getId
.and.returnValue("something-other-than-the-" + testDefaultRoot);
instantiateController();
return waitsForNavigation().then(function () {
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
it("does not try to override navigation", function () {
mockNavigationService.getNavigation.and.returnValue(mockDefaultRootObject);
instantiateController();
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockDefaultRootObject);
});
});
it("updates scope when navigated object changes", function () {
// Should have registered a listener - call it
mockNavigationService.addListener.calls.mostRecent().args[0](
mockOtherDomainObject
);
expect(mockScope.navigatedObject).toEqual(mockOtherDomainObject);
});
it("releases its navigation listener when its scope is destroyed", function () {
expect(mockScope.$on).toHaveBeenCalledWith(
"$destroy",
jasmine.any(Function)
);
mockScope.$on.calls.mostRecent().args[1]();
// Should remove the listener it added earlier
expect(mockNavigationService.removeListener).toHaveBeenCalledWith(
mockNavigationService.addListener.calls.mostRecent().args[0]
);
});
it("uses route parameters to choose initially-navigated object", function () {
mockRoute.current.params.ids = testDefaultRoot + "/next";
instantiateController();
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
});
});
it("handles invalid IDs by going as far as possible", function () {
// Idea here is that if we get a bad path of IDs,
// browse controller should traverse down it until
// it hits an invalid ID.
mockRoute.current.params.ids = testDefaultRoot + "/junk";
instantiateController();
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockDefaultRootObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
it("handles compositionless objects by going as far as possible", function () {
// Idea here is that if we get a path which passes
// through an object without a composition, browse controller
// should stop at it since remaining IDs cannot be loaded.
mockRoute.current.params.ids = testDefaultRoot + "/next/junk";
instantiateController();
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
});
});
it("updates the displayed route to reflect current navigation", function () {
// In order to trigger a route update and not a route change,
// the current route must be updated before location.path is
// called.
expect(mockRoute.current.pathParams.ids)
.not
.toBe(testDefaultRoot + '/next');
mockLocation.path.and.callFake(function () {
expect(mockRoute.current.pathParams.ids)
.toBe(testDefaultRoot + '/next');
});
mockNavigationService.addListener.calls.mostRecent().args[0](
mockNextObject
);
expect(mockLocation.path).toHaveBeenCalledWith(
'/browse/' + testDefaultRoot + '/next'
);
});
});
}
);

View File

@ -0,0 +1,93 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
["../src/BrowseObjectController"],
function (BrowseObjectController) {
describe("The browse object controller", function () {
var mockScope,
mockLocation,
mockRoute,
controller;
// Utility function; look for a $watch on scope and fire it
function fireWatch(expr, value) {
mockScope.$watch.calls.all().forEach(function (call) {
if (call.args[0] === expr) {
call.args[1](value);
}
});
}
beforeEach(function () {
mockScope = jasmine.createSpyObj(
"$scope",
["$on", "$watch"]
);
mockRoute = { current: { params: {} } };
mockLocation = jasmine.createSpyObj(
"$location",
["path", "search"]
);
mockLocation.search.and.returnValue({});
controller = new BrowseObjectController(
mockScope,
mockLocation,
mockRoute
);
});
it("updates query parameters when selected view changes", function () {
fireWatch("representation.selected.key", "xyz");
expect(mockLocation.search).toHaveBeenCalledWith('view', "xyz");
// Allows the path index to be checked
// prior to setting $route.current
mockLocation.path.and.returnValue("/browse/");
});
it("sets the active view from query parameters", function () {
var mockDomainObject = jasmine.createSpyObj(
"domainObject",
['getId', 'getModel', 'getCapability', 'useCapability']
),
testViews = [
{ key: 'abc' },
{ key: 'def', someKey: 'some value' },
{ key: 'xyz' }
];
mockDomainObject.useCapability.and.callFake(function (c) {
return (c === 'view') && testViews;
});
mockLocation.search.and.returnValue({ view: 'def' });
fireWatch('domainObject', mockDomainObject);
expect(mockScope.representation.selected)
.toEqual(testViews[1]);
});
});
}
);

View File

@ -0,0 +1,103 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
["../src/InspectorPaneController"],
function (InspectorPaneController) {
describe("The InspectorPaneController", function () {
var mockScope,
mockAgentService,
mockDomainObject,
mockWindow,
mockStatusCapability,
mockNavigationService,
mockNavigationUnlistener,
mockStatusUnlistener,
controller,
mockLocation,
mockAttrs;
beforeEach(function () {
mockScope = jasmine.createSpyObj("$scope", ["$on"]);
mockWindow = jasmine.createSpyObj("$window", ["open"]);
mockAgentService = jasmine.createSpyObj(
"agentService",
["isMobile", "isPhone", "isTablet", "isPortrait", "isLandscape"]
);
mockNavigationUnlistener = jasmine.createSpy("navigationUnlistener");
mockNavigationService = jasmine.createSpyObj(
"navigationService",
["getNavigation", "addListener"]
);
mockNavigationService.addListener.and.returnValue(mockNavigationUnlistener);
mockStatusUnlistener = jasmine.createSpy("statusUnlistener");
mockStatusCapability = jasmine.createSpyObj(
"statusCapability",
["listen"]
);
mockStatusCapability.listen.and.returnValue(mockStatusUnlistener);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
[
'getId',
'getModel',
'getCapability',
'hasCapability'
]
);
mockDomainObject.getId.and.returnValue("domainObject");
mockDomainObject.getModel.and.returnValue({});
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.returnValue(mockStatusCapability);
mockLocation = jasmine.createSpyObj('location', ['search']);
mockLocation.search.and.returnValue({});
mockAttrs = {};
controller = new InspectorPaneController(mockScope, mockAgentService, mockWindow, mockNavigationService, mockLocation, mockAttrs);
});
it("listens for changes to navigation and attaches a status" +
" listener", function () {
expect(mockNavigationService.addListener).toHaveBeenCalledWith(jasmine.any(Function));
mockNavigationService.addListener.calls.mostRecent().args[0](mockDomainObject);
expect(mockStatusCapability.listen).toHaveBeenCalledWith(jasmine.any(Function));
});
it("if hidden, shows the inspector when domain object switches to" +
" edit mode", function () {
controller.toggle();
// test pre-condition that inspector is hidden
expect(controller.visible()).toBe(false);
mockNavigationService.addListener.calls.mostRecent().args[0](mockDomainObject);
mockStatusCapability.listen.calls.mostRecent().args[0](["editing"]);
expect(controller.visible()).toBe(true);
});
});
}
);

View File

@ -0,0 +1,79 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* MenuArrowControllerSpec. Created by shale on 07/02/2015.
*/
define(
["../src/MenuArrowController"],
function (MenuArrowController) {
describe("The menu arrow controller ", function () {
var mockScope,
mockDomainObject,
mockEvent,
mockContextMenuAction,
mockActionContext,
controller;
beforeEach(function () {
mockScope = jasmine.createSpyObj(
"$scope",
[""]
);
mockDomainObject = jasmine.createSpyObj(
"domainObject",
["getCapability"]
);
mockEvent = jasmine.createSpyObj(
"event",
["preventDefault"]
);
mockContextMenuAction = jasmine.createSpyObj(
"action",
["perform", "getActions"]
);
mockActionContext = jasmine.createSpyObj(
"actionContext",
[""]
);
mockActionContext.domainObject = mockDomainObject;
mockActionContext.event = mockEvent;
mockScope.domainObject = mockDomainObject;
mockDomainObject.getCapability.and.returnValue(mockContextMenuAction);
mockContextMenuAction.perform.and.returnValue(jasmine.any(Function));
controller = new MenuArrowController(mockScope);
});
it("calls the context menu action when clicked", function () {
// Simulate a click on the menu arrow
controller.showMenu(mockEvent);
// Expect the menu action to be performed
expect(mockDomainObject.getCapability).toHaveBeenCalledWith('action');
expect(mockContextMenuAction.perform).toHaveBeenCalled();
});
});
}
);

View File

@ -0,0 +1,137 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
["../src/ObjectHeaderController"],
function (ObjectHeaderController) {
describe("The object header controller", function () {
var mockScope,
mockDomainObject,
mockCapabilities,
mockMutationCapability,
mockTypeCapability,
mockEvent,
mockCurrentTarget,
model,
controller;
beforeEach(function () {
mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
mockTypeCapability = jasmine.createSpyObj("type", ["typeDef", "hasFeature"]);
mockTypeCapability.typeDef = { name: ""};
mockTypeCapability.hasFeature.and.callFake(function (feature) {
return feature === 'creation';
});
mockCapabilities = {
mutation: mockMutationCapability,
type: mockTypeCapability
};
model = {
name: "Test name"
};
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "getModel"]);
mockDomainObject.getModel.and.returnValue(model);
mockDomainObject.getCapability.and.callFake(function (key) {
return mockCapabilities[key];
});
mockScope = {
domainObject: mockDomainObject
};
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "textContent"]);
mockCurrentTarget.blur.and.returnValue(mockCurrentTarget);
mockEvent = {
which: {},
type: {},
currentTarget: mockCurrentTarget
};
controller = new ObjectHeaderController(mockScope);
});
it("updates the model with new name on blur", function () {
mockEvent.type = "blur";
mockCurrentTarget.textContent = "New name";
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
it("updates the model with a default for blank names", function () {
mockEvent.type = "blur";
mockCurrentTarget.textContent = "";
controller.updateName(mockEvent);
expect(mockCurrentTarget.textContent.length).not.toEqual(0);
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
it("does not update the model if the same name", function () {
mockEvent.type = "blur";
mockCurrentTarget.textContent = mockDomainObject.getModel().name;
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
});
it("updates the model on enter keypress event only", function () {
mockCurrentTarget.textContent = "New name";
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
mockMutationCapability.mutate.calls.mostRecent().args[0](model);
expect(mockDomainObject.getModel().name).toBe("New name");
});
it("blurs the field on enter key press", function () {
mockCurrentTarget.textContent = "New name";
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
});
it("allows editting name when object is creatable", function () {
expect(controller.allowEdit()).toBe(true);
});
it("disallows editting name when object is non-creatable", function () {
mockTypeCapability.hasFeature.and.returnValue(false);
expect(controller.allowEdit()).toBe(false);
});
});
}
);

View File

@ -0,0 +1,106 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
["../src/PaneController"],
function (PaneController) {
describe("The PaneController", function () {
var mockScope,
mockAgentService,
mockWindow,
controller,
mockLocation,
mockAttrs;
// We want to reinstantiate for each test case
// because device state can influence constructor-time behavior
function instantiateController() {
return new PaneController(
mockScope,
mockAgentService,
mockWindow,
mockLocation,
mockAttrs
);
}
beforeEach(function () {
mockScope = jasmine.createSpyObj("$scope", ["$on"]);
mockAgentService = jasmine.createSpyObj(
"agentService",
["isMobile", "isPhone", "isTablet", "isPortrait", "isLandscape"]
);
mockWindow = jasmine.createSpyObj("$window", ["open"]);
mockLocation = jasmine.createSpyObj('location', ['search']);
mockLocation.search.and.returnValue({});
mockAttrs = {};
});
it("is initially visible", function () {
expect(instantiateController().visible()).toBeTruthy();
});
it("allows visibility to be toggled", function () {
controller = instantiateController();
controller.toggle();
expect(controller.visible()).toBeFalsy();
controller.toggle();
expect(controller.visible()).toBeTruthy();
});
it("collapses on navigation changes on portrait-oriented phones", function () {
mockAgentService.isMobile.and.returnValue(true);
mockAgentService.isPhone.and.returnValue(true);
mockAgentService.isPortrait.and.returnValue(true);
controller = instantiateController();
expect(controller.visible()).toBeTruthy();
// Simulate a change from the tree by invoking controller's
controller.callback();
// Tree should have collapsed
expect(controller.visible()).toBeFalsy();
});
describe("specifying hideParameter", function () {
beforeEach(function () {
mockAttrs = {hideParameter: 'hideTree'};
});
it("sets pane state to false when in location.search", function () {
mockLocation.search.and.returnValue({'hideTree': true});
expect(instantiateController().visible()).toBe(false);
expect(mockLocation.search).toHaveBeenCalledWith('hideTree', undefined);
});
it("sets state to true when not found in location.search", function () {
mockLocation.search.and.returnValue({});
expect(instantiateController().visible()).toBe(true);
expect(mockLocation.search).not.toHaveBeenCalledWith('hideTree', undefined);
});
});
});
}
);

View File

@ -30,7 +30,8 @@ define([
"./res/templates/message.html", "./res/templates/message.html",
"./res/templates/notification-message.html", "./res/templates/notification-message.html",
"./res/templates/overlay-message-list.html", "./res/templates/overlay-message-list.html",
"./res/templates/overlay.html" "./res/templates/overlay.html",
'legacyRegistry'
], function ( ], function (
DialogService, DialogService,
OverlayService, OverlayService,
@ -41,12 +42,11 @@ define([
messageTemplate, messageTemplate,
notificationMessageTemplate, notificationMessageTemplate,
overlayMessageListTemplate, overlayMessageListTemplate,
overlayTemplate overlayTemplate,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/dialog", {
name:"platform/commonUI/dialog",
definition: {
"extensions": { "extensions": {
"services": [ "services": [
{ {
@ -107,6 +107,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -6,12 +6,6 @@
ng-show="ngModel.dialog.messages.length > 1 || ng-show="ngModel.dialog.messages.length > 1 ||
ngModel.dialog.messages.length == 0">s</span> ngModel.dialog.messages.length == 0">s</span>
</div> </div>
<button
ng-if="ngModel.dialog.topBarButton"
class="c-button c-button--major"
ng-click="ngModel.topBarButton.onClick">
{{ ngModel.topBarButton.label }}
</button>
</div> </div>
<div class="w-messages c-overlay__messages"> <div class="w-messages c-overlay__messages">
<mct-include <mct-include
@ -22,7 +16,7 @@
<button ng-repeat="dialogAction in ngModel.dialog.actions" <button ng-repeat="dialogAction in ngModel.dialog.actions"
class="c-button c-button--major" class="c-button c-button--major"
ng-click="dialogAction.action()"> ng-click="dialogAction.action()">
{{ dialogAction.label }} {{dialogAction.label}}
</button> </button>
</div> </div>
</div> </div>

View File

@ -27,6 +27,7 @@ define([
"./src/actions/EditAndComposeAction", "./src/actions/EditAndComposeAction",
"./src/actions/EditAction", "./src/actions/EditAction",
"./src/actions/PropertiesAction", "./src/actions/PropertiesAction",
"./src/actions/RemoveAction",
"./src/actions/SaveAction", "./src/actions/SaveAction",
"./src/actions/SaveAndStopEditingAction", "./src/actions/SaveAndStopEditingAction",
"./src/actions/SaveAsAction", "./src/actions/SaveAsAction",
@ -48,7 +49,8 @@ define([
"./res/templates/library.html", "./res/templates/library.html",
"./res/templates/edit-object.html", "./res/templates/edit-object.html",
"./res/templates/edit-action-buttons.html", "./res/templates/edit-action-buttons.html",
"./res/templates/topbar-edit.html" "./res/templates/topbar-edit.html",
'legacyRegistry'
], function ( ], function (
EditActionController, EditActionController,
EditPanesController, EditPanesController,
@ -56,6 +58,7 @@ define([
EditAndComposeAction, EditAndComposeAction,
EditAction, EditAction,
PropertiesAction, PropertiesAction,
RemoveAction,
SaveAction, SaveAction,
SaveAndStopEditingAction, SaveAndStopEditingAction,
SaveAsAction, SaveAsAction,
@ -77,11 +80,11 @@ define([
libraryTemplate, libraryTemplate,
editObjectTemplate, editObjectTemplate,
editActionButtonsTemplate, editActionButtonsTemplate,
topbarEditTemplate topbarEditTemplate,
legacyRegistry
) { ) {
return {
name: "platform/commonUI/edit", legacyRegistry.register("platform/commonUI/edit", {
definition: {
"extensions": { "extensions": {
"controllers": [ "controllers": [
{ {
@ -155,6 +158,18 @@ define([
"dialogService" "dialogService"
] ]
}, },
{
"key": "remove",
"category": "legacy",
"implementation": RemoveAction,
"cssClass": "icon-trash",
"name": "Remove",
"description": "Remove this object from its containing object.",
"depends": [
"openmct",
"navigationService"
]
},
{ {
"key": "save-and-stop-editing", "key": "save-and-stop-editing",
"category": "save", "category": "save",
@ -348,6 +363,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -0,0 +1,131 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* Module defining RemoveAction. Created by vwoeltje on 11/17/14.
*/
define([], function () {
/**
* Construct an action which will remove the provided object manifestation.
* The object will be removed from its parent's composition; the parent
* is looked up via the "context" capability (so this will be the
* immediate ancestor by which this specific object was reached.)
*
* @param {DialogService} dialogService a service which will show the dialog
* @param {NavigationService} navigationService a service that maintains the current navigation state
* @param {ActionContext} context the context in which this action is performed
* @memberof platform/commonUI/edit
* @constructor
* @implements {Action}
*/
function RemoveAction(openmct, navigationService, context) {
this.domainObject = (context || {}).domainObject;
this.openmct = openmct;
this.navigationService = navigationService;
}
/**
* Perform this action.
*/
RemoveAction.prototype.perform = function () {
var dialog,
domainObject = this.domainObject,
navigationService = this.navigationService;
/*
* Check whether an object ID matches the ID of the object being
* removed (used to filter a parent's composition to handle the
* removal.)
*/
function isNotObject(otherObjectId) {
return otherObjectId !== domainObject.getId();
}
/*
* Mutate a parent object such that it no longer contains the object
* which is being removed.
*/
function doMutate(model) {
model.composition = model.composition.filter(isNotObject);
}
/*
* Checks current object and ascendants of current
* object with object being removed, if the current
* object or any in the current object's path is being removed,
* navigate back to parent of removed object.
*/
function checkObjectNavigation(object, parentObject) {
// Traverse object starts at current location
var traverseObject = (navigationService).getNavigation(),
context;
// Stop when object is not defined (above ROOT)
while (traverseObject) {
// If object currently traversed to is object being removed
// navigate to parent of current object and then exit loop
if (traverseObject.getId() === object.getId()) {
navigationService.setNavigation(parentObject);
return;
}
// Traverses to parent of current object, moving
// up the ascendant path
context = traverseObject.getCapability('context');
traverseObject = context && context.getParent();
}
}
/*
* Remove the object from its parent, as identified by its context
* capability. Based on object's location and selected object's location
* user may be navigated to existing parent object
*/
function removeFromContext() {
var contextCapability = domainObject.getCapability('context'),
parent = contextCapability.getParent();
// If currently within path of removed object(s),
// navigates to existing object up tree
checkObjectNavigation(domainObject, parent);
return parent.useCapability('mutation', doMutate);
}
removeFromContext();
};
// Object needs to have a parent for Remove to be applicable
RemoveAction.appliesTo = function (context) {
var object = (context || {}).domainObject,
contextCapability = object && object.getCapability("context"),
parent = contextCapability && contextCapability.getParent(),
parentType = parent && parent.getCapability('type'),
parentCreatable = parentType && parentType.hasFeature('creation');
// Only creatable types should be modifiable
return parent !== undefined &&
Array.isArray(parent.getModel().composition) &&
parentCreatable;
};
return RemoveAction;
});

View File

@ -6,7 +6,7 @@ define([], function () {
SaveInProgressDialog.prototype.show = function () { SaveInProgressDialog.prototype.show = function () {
this.dialog = this.dialogService.showBlockingMessage({ this.dialog = this.dialogService.showBlockingMessage({
title: "Saving", title: "Saving...",
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.", hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
unknownProgress: true, unknownProgress: true,
severity: "info", severity: "info",

View File

@ -21,7 +21,7 @@
*****************************************************************************/ *****************************************************************************/
define( define(
['objectUtils'], ['../../../../../src/api/objects/object-utils'],
function (objectUtils) { function (objectUtils) {
/** /**

View File

@ -0,0 +1,255 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
["../../src/actions/RemoveAction"],
function (RemoveAction) {
describe("The Remove action", function () {
var action,
actionContext,
capabilities,
mockContext,
mockOverlayAPI,
mockDomainObject,
mockMutation,
mockNavigationService,
mockParent,
mockType,
model;
beforeEach(function () {
mockDomainObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability", "getModel"]
);
mockMutation = jasmine.createSpyObj("mutation", ["invoke"]);
mockType = jasmine.createSpyObj("type", ["hasFeature"]);
mockType.hasFeature.and.returnValue(true);
capabilities = {
mutation: mockMutation,
type: mockType
};
model = {
composition: ["a", "test", "b"]
};
mockParent = {
getModel: function () {
return model;
},
getCapability: function (k) {
return capabilities[k];
},
useCapability: function (k, v) {
return capabilities[k].invoke(v);
}
};
mockOverlayAPI = jasmine.createSpyObj(
"overlayAPI",
["dialog"]
);
mockNavigationService = jasmine.createSpyObj(
"navigationService",
[
"getNavigation",
"setNavigation",
"addListener",
"removeListener"
]
);
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
mockContext = jasmine.createSpyObj("context", ["getParent"]);
mockContext.getParent.and.returnValue(mockParent);
mockDomainObject.getId.and.returnValue("test");
mockDomainObject.getCapability.and.returnValue(mockContext);
mockDomainObject.getModel.and.returnValue({name: 'test object'});
mockContext.getParent.and.returnValue(mockParent);
mockType.hasFeature.and.returnValue(true);
actionContext = { domainObject: mockDomainObject };
action = new RemoveAction({overlays: mockOverlayAPI}, mockNavigationService, actionContext);
});
it("only applies to objects with parents", function () {
expect(RemoveAction.appliesTo(actionContext)).toBeTruthy();
mockContext.getParent.and.returnValue(undefined);
expect(RemoveAction.appliesTo(actionContext)).toBeFalsy();
// Also verify that creatability was checked
expect(mockType.hasFeature).toHaveBeenCalledWith('creation');
});
it("shows a blocking message dialog", function () {
mockParent = jasmine.createSpyObj(
"parent",
["getModel", "getCapability", "useCapability"]
);
action.perform();
expect(mockOverlayAPI.dialog).toHaveBeenCalled();
// Also check that no mutation happens at this point
expect(mockParent.useCapability).not.toHaveBeenCalledWith("mutation", jasmine.any(Function));
});
describe("after the remove callback is triggered", function () {
var mockChildContext,
mockChildObject,
mockDialogHandle,
mockGrandchildContext,
mockGrandchildObject,
mockRootContext,
mockRootObject;
beforeEach(function () {
mockChildObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockDialogHandle = jasmine.createSpyObj(
"dialogHandle",
["dismiss"]
);
mockGrandchildObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockRootObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockChildContext = jasmine.createSpyObj("context", ["getParent"]);
mockGrandchildContext = jasmine.createSpyObj("context", ["getParent"]);
mockRootContext = jasmine.createSpyObj("context", ["getParent"]);
mockOverlayAPI.dialog.and.returnValue(mockDialogHandle);
});
it("mutates the parent when performed", function () {
action.perform();
mockOverlayAPI.dialog.calls.mostRecent().args[0]
.buttons[0].callback();
expect(mockMutation.invoke)
.toHaveBeenCalledWith(jasmine.any(Function));
});
it("changes composition from its mutation function", function () {
var mutator, result;
action.perform();
mockOverlayAPI.dialog.calls.mostRecent().args[0]
.buttons[0].callback();
mutator = mockMutation.invoke.calls.mostRecent().args[0];
result = mutator(model);
// Should not have cancelled the mutation
expect(result).not.toBe(false);
// Simulate mutate's behavior (remove can either return a
// new model or modify this one in-place)
result = result || model;
// Should have removed "test" - that was our
// mock domain object's id.
expect(result.composition).toEqual(["a", "b"]);
});
it("removes parent of object currently navigated to", function () {
// Navigates to child object
mockNavigationService.getNavigation.and.returnValue(mockChildObject);
// Test is id of object being removed
// Child object has different id
mockDomainObject.getId.and.returnValue("test");
mockChildObject.getId.and.returnValue("not test");
// Sets context for the child and domainObject
mockDomainObject.getCapability.and.returnValue(mockContext);
mockChildObject.getCapability.and.returnValue(mockChildContext);
// Parents of child and domainObject are set
mockContext.getParent.and.returnValue(mockParent);
mockChildContext.getParent.and.returnValue(mockDomainObject);
mockType.hasFeature.and.returnValue(true);
action.perform();
mockOverlayAPI.dialog.calls.mostRecent().args[0]
.buttons[0].callback();
// Expects navigation to parent of domainObject (removed object)
expect(mockNavigationService.setNavigation).toHaveBeenCalledWith(mockParent);
});
it("checks if removing object not in ascendent path (reaches ROOT)", function () {
// Navigates to grandchild of ROOT
mockNavigationService.getNavigation.and.returnValue(mockGrandchildObject);
// domainObject (grandparent) is set as ROOT, child and grandchild
// are set objects not being removed
mockDomainObject.getId.and.returnValue("test 1");
mockRootObject.getId.and.returnValue("ROOT");
mockChildObject.getId.and.returnValue("not test 2");
mockGrandchildObject.getId.and.returnValue("not test 3");
// Sets context for the grandchild, child, and domainObject
mockRootObject.getCapability.and.returnValue(mockRootContext);
mockChildObject.getCapability.and.returnValue(mockChildContext);
mockGrandchildObject.getCapability.and.returnValue(mockGrandchildContext);
// Parents of grandchild and child are set
mockChildContext.getParent.and.returnValue(mockRootObject);
mockGrandchildContext.getParent.and.returnValue(mockChildObject);
mockType.hasFeature.and.returnValue(true);
action.perform();
mockOverlayAPI.dialog.calls.mostRecent().args[0]
.buttons[0].callback();
// Expects no navigation to occur
expect(mockNavigationService.setNavigation).not.toHaveBeenCalled();
});
});
});
}
);

View File

@ -25,7 +25,7 @@ define(
["../../src/actions/SaveAsAction"], ["../../src/actions/SaveAsAction"],
function (SaveAsAction) { function (SaveAsAction) {
xdescribe("The Save As action", function () { describe("The Save As action", function () {
var mockDomainObject, var mockDomainObject,
mockClonedObject, mockClonedObject,
mockEditorCapability, mockEditorCapability,

View File

@ -24,7 +24,7 @@ define(
["../../src/capabilities/EditorCapability"], ["../../src/capabilities/EditorCapability"],
function (EditorCapability) { function (EditorCapability) {
xdescribe("The editor capability", function () { describe("The editor capability", function () {
var mockDomainObject, var mockDomainObject,
capabilities, capabilities,
mockParentObject, mockParentObject,

View File

@ -27,7 +27,7 @@ define(
["../../src/creation/CreateAction"], ["../../src/creation/CreateAction"],
function (CreateAction) { function (CreateAction) {
xdescribe("The create action", function () { describe("The create action", function () {
var mockType, var mockType,
mockParent, mockParent,
mockContext, mockContext,

View File

@ -27,7 +27,7 @@ define(
["../../src/creation/CreateWizard"], ["../../src/creation/CreateWizard"],
function (CreateWizard) { function (CreateWizard) {
xdescribe("The create wizard", function () { describe("The create wizard", function () {
var mockType, var mockType,
mockParent, mockParent,
mockProperties, mockProperties,

View File

@ -23,16 +23,16 @@
define([ define([
"./src/FormatProvider", "./src/FormatProvider",
"./src/UTCTimeFormat", "./src/UTCTimeFormat",
"./src/DurationFormat" "./src/DurationFormat",
'legacyRegistry'
], function ( ], function (
FormatProvider, FormatProvider,
UTCTimeFormat, UTCTimeFormat,
DurationFormat DurationFormat,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/formats", {
name:"platform/commonUI/formats",
definition: {
"name": "Format Registry", "name": "Format Registry",
"description": "Provides a registry for formats, which allow parsing and formatting of values.", "description": "Provides a registry for formats, which allow parsing and formatting of values.",
"extensions": { "extensions": {
@ -74,6 +74,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -66,7 +66,8 @@ define([
"./res/templates/object-inspector.html", "./res/templates/object-inspector.html",
"./res/templates/controls/selector.html", "./res/templates/controls/selector.html",
"./res/templates/controls/datetime-picker.html", "./res/templates/controls/datetime-picker.html",
"./res/templates/controls/datetime-field.html" "./res/templates/controls/datetime-field.html",
'legacyRegistry'
], function ( ], function (
UrlService, UrlService,
PopupService, PopupService,
@ -113,12 +114,11 @@ define([
objectInspectorTemplate, objectInspectorTemplate,
selectorTemplate, selectorTemplate,
datetimePickerTemplate, datetimePickerTemplate,
datetimeFieldTemplate datetimeFieldTemplate,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/general", {
name:"platform/commonUI/general",
definition: {
"name": "General UI elements", "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", "resources": "res",
@ -524,6 +524,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -21,6 +21,7 @@
--> -->
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! --> <!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<div class="c-indicator {{ngModel.getCssClass()}}" <div class="c-indicator {{ngModel.getCssClass()}}"
title="{{ngModel.getDescription()}}"
ng-show="ngModel.getText().length > 0"> ng-show="ngModel.getText().length > 0">
<span class="label c-indicator__label">{{ngModel.getText()}}</span> <span class="label">{{ngModel.getText()}}</span>
</div> </div>

View File

@ -26,7 +26,7 @@ define([
'zepto' 'zepto'
], function (TreeView, $) { ], function (TreeView, $) {
xdescribe("TreeView", function () { describe("TreeView", function () {
var mockGestureService, var mockGestureService,
mockGestureHandle, mockGestureHandle,
mockDomainObject, mockDomainObject,

View File

@ -27,7 +27,8 @@ define([
"./res/info-table.html", "./res/info-table.html",
"./res/info-bubble.html", "./res/info-bubble.html",
"./res/bubble.html", "./res/bubble.html",
"./res/templates/info-button.html" "./res/templates/info-button.html",
'legacyRegistry'
], function ( ], function (
InfoGesture, InfoGesture,
InfoButtonGesture, InfoButtonGesture,
@ -35,12 +36,11 @@ define([
infoTableTemplate, infoTableTemplate,
infoBubbleTemplate, infoBubbleTemplate,
bubbleTemplate, bubbleTemplate,
infoButtonTemplate infoButtonTemplate,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/inspect", {
name:"platform/commonUI/inspect",
definition: {
"extensions": { "extensions": {
"templates": [ "templates": [
{ {
@ -112,6 +112,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -23,16 +23,16 @@
define([ define([
"./src/MCTDevice", "./src/MCTDevice",
"./src/AgentService", "./src/AgentService",
"./src/DeviceClassifier" "./src/DeviceClassifier",
'legacyRegistry'
], function ( ], function (
MCTDevice, MCTDevice,
AgentService, AgentService,
DeviceClassifier DeviceClassifier,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/mobile", {
name:"platform/commonUI/mobile",
definition: {
"extensions": { "extensions": {
"directives": [ "directives": [
{ {
@ -62,6 +62,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -21,15 +21,44 @@
*****************************************************************************/ *****************************************************************************/
define([ define([
"./src/NotificationService" "./src/NotificationIndicatorController",
"./src/NotificationIndicator",
"./src/NotificationService",
"./res/notification-indicator.html",
'legacyRegistry'
], function ( ], function (
NotificationService NotificationIndicatorController,
NotificationIndicator,
NotificationService,
notificationIndicatorTemplate,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/notification", {
name:"platform/commonUI/notification",
definition: {
"extensions": { "extensions": {
"templates": [
{
"key": "notificationIndicatorTemplate",
"template": notificationIndicatorTemplate
}
],
"controllers": [
{
"key": "NotificationIndicatorController",
"implementation": NotificationIndicatorController,
"depends": [
"$scope",
"openmct",
"dialogService"
]
}
],
"indicators": [
{
"implementation": NotificationIndicator,
"priority": "fallback"
}
],
"services": [ "services": [
{ {
"key": "notificationService", "key": "notificationService",
@ -42,6 +71,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -0,0 +1,8 @@
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<div ng-show="notifications.length > 0" class="c-indicator c-indicator--clickable s-status-{{highest.severity}} icon-bell"
ng-controller="NotificationIndicatorController">
<span class="label">
<a ng-click="showNotificationsList()">
{{notifications.length}} Notification<span ng-show="notifications.length > 1">s</span></a>
</span><span class="count">{{notifications.length}}</span>
</div>

View File

@ -1,5 +1,5 @@
/***************************************************************************** /*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, United States Government * Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space * as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved. * Administration. All rights reserved.
* *
@ -19,10 +19,15 @@
* this source code distribution or the Licensing information page available * this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
import URLTimeSettingsSynchronizer from "./URLTimeSettingsSynchronizer.js";
export default function () { define(
return function install(openmct) { [],
return new URLTimeSettingsSynchronizer(openmct); function () {
function NotificationIndicator() {}
NotificationIndicator.template = 'notificationIndicatorTemplate';
return NotificationIndicator;
} }
} );

View File

@ -0,0 +1,73 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[],
function () {
/**
* Provides an indicator that is visible when there are
* banner notifications that have been minimized. Will also indicate
* the number of notifications. Notifications can be viewed by
* clicking on the indicator to launch a dialog showing a list of
* notifications.
* @param $scope
* @param notificationService
* @param dialogService
* @constructor
*/
function NotificationIndicatorController($scope, openmct, dialogService) {
$scope.notifications = openmct.notifications.notifications;
$scope.highest = openmct.notifications.highest;
/**
* Launch a dialog showing a list of current notifications.
*/
$scope.showNotificationsList = function () {
let notificationsList = openmct.notifications.notifications.map(notification => {
if (notification.model.severity === 'alert' || notification.model.severity === 'info') {
notification.model.primaryOption = {
label: 'Dismiss',
callback: () => {
let currentIndex = notificationsList.indexOf(notification);
notification.dismiss();
notificationsList.splice(currentIndex, 1);
}
}
}
return notification;
})
dialogService.getDialogResponse('overlay-message-list', {
dialog: {
title: "Messages",
//Launch the message list dialog with the models
// from the notifications
messages: notificationsList
}
});
};
}
return NotificationIndicatorController;
}
);

View File

@ -0,0 +1,60 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
['../src/NotificationIndicatorController'],
function (NotificationIndicatorController) {
describe("The notification indicator controller ", function () {
var mockNotificationService,
mockScope,
mockDialogService,
controller;
beforeEach(function () {
mockNotificationService = jasmine.createSpy("notificationService");
mockScope = jasmine.createSpy("$scope");
mockDialogService = jasmine.createSpyObj(
"dialogService",
["getDialogResponse","dismiss"]
);
mockNotificationService.highest = {
severity: "error"
};
controller = new NotificationIndicatorController(mockScope, mockNotificationService, mockDialogService);
});
it("exposes the highest notification severity to the template", function () {
expect(mockScope.highest).toBeTruthy();
expect(mockScope.highest.severity).toBe("error");
});
it("invokes the dialog service to show list of messages", function () {
expect(mockScope.showNotificationsList).toBeDefined();
mockScope.showNotificationsList();
expect(mockDialogService.getDialogResponse).toHaveBeenCalled();
expect(mockDialogService.getDialogResponse.calls.mostRecent().args[0]).toBe('overlay-message-list');
expect(mockDialogService.getDialogResponse.calls.mostRecent().args[1].dialog).toBeDefined();
});
});
}
);

View File

@ -22,15 +22,15 @@
define([ define([
'./src/InspectorController', './src/InspectorController',
'./src/EditableRegionPolicy' './src/EditableRegionPolicy',
'legacyRegistry'
], function ( ], function (
InspectorController, InspectorController,
EditableRegionPolicy EditableRegionPolicy,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/commonUI/regions", {
name:"platform/commonUI/regions",
definition: {
"extensions": { "extensions": {
"controllers": [ "controllers": [
{ {
@ -50,6 +50,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -25,18 +25,18 @@ define([
"./src/CompositionMutabilityPolicy", "./src/CompositionMutabilityPolicy",
"./src/CompositionModelPolicy", "./src/CompositionModelPolicy",
"./src/ComposeActionPolicy", "./src/ComposeActionPolicy",
"./src/PersistableCompositionPolicy" "./src/PersistableCompositionPolicy",
'legacyRegistry'
], function ( ], function (
CompositionPolicy, CompositionPolicy,
CompositionMutabilityPolicy, CompositionMutabilityPolicy,
CompositionModelPolicy, CompositionModelPolicy,
ComposeActionPolicy, ComposeActionPolicy,
PersistableCompositionPolicy PersistableCompositionPolicy,
legacyRegistry
) { ) {
return { legacyRegistry.register("platform/containment", {
name:"platform/containment",
definition: {
"extensions": { "extensions": {
"policies": [ "policies": [
{ {
@ -71,6 +71,5 @@ define([
} }
] ]
} }
} });
};
}); });

View File

@ -26,7 +26,7 @@
* @namespace platform/containment * @namespace platform/containment
*/ */
define( define(
['objectUtils'], ['../../../src/api/objects/object-utils'],
function (objectUtils) { function (objectUtils) {
function PersistableCompositionPolicy(openmct) { function PersistableCompositionPolicy(openmct) {

Some files were not shown because too many files have changed in this diff Show More