mirror of
https://github.com/nasa/openmct.git
synced 2025-07-03 05:22:52 +00:00
Compare commits
1 Commits
plotly-tes
...
refresh-op
Author | SHA1 | Date | |
---|---|---|---|
4992b99aa5 |
@ -2,7 +2,7 @@ version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/node:13-browsers
|
||||
- image: circleci/node:8-browsers
|
||||
environment:
|
||||
CHROME_BIN: "/usr/bin/google-chrome"
|
||||
steps:
|
||||
@ -11,7 +11,7 @@ jobs:
|
||||
name: Update npm
|
||||
command: 'sudo npm install -g npm@latest'
|
||||
- restore_cache:
|
||||
key: dependency-cache-node-13-{{ checksum "package.json" }}
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: Installing dependencies (npm install)
|
||||
command: npm install
|
||||
@ -20,8 +20,8 @@ jobs:
|
||||
paths:
|
||||
- node_modules
|
||||
- run:
|
||||
name: npm run test:coverage
|
||||
command: npm run test:coverage
|
||||
name: npm run test
|
||||
command: npm run test
|
||||
- run:
|
||||
name: npm run lint
|
||||
command: npm run lint
|
||||
|
64
.eslintrc.js
64
.eslintrc.js
@ -1,4 +1,3 @@
|
||||
const LEGACY_FILES = ["platform/**", "example/**"];
|
||||
module.exports = {
|
||||
"env": {
|
||||
"browser": true,
|
||||
@ -11,8 +10,7 @@ module.exports = {
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/recommended",
|
||||
"plugin:you-dont-need-lodash-underscore/compatible"
|
||||
"plugin:vue/recommended"
|
||||
],
|
||||
"parser": "vue-eslint-parser",
|
||||
"parserOptions": {
|
||||
@ -24,9 +22,6 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"curly": "error",
|
||||
"eqeqeq": "error",
|
||||
@ -71,56 +66,6 @@ module.exports = {
|
||||
],
|
||||
"dot-notation": "error",
|
||||
"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,
|
||||
@ -167,13 +112,6 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"files": LEGACY_FILES,
|
||||
"rules": {
|
||||
// https://eslint.org/docs/rules/no-nested-ternary
|
||||
"no-nested-ternary": "off",
|
||||
"no-var": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -38,4 +38,3 @@ protractor/logs
|
||||
npm-debug.log
|
||||
|
||||
package-lock.json
|
||||
report.*.json
|
||||
|
4
API.md
4
API.md
@ -427,8 +427,8 @@ Each telemetry value description has an object defining hints. Keys in this thi
|
||||
|
||||
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.
|
||||
* `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.
|
||||
* `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`: 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.
|
||||
|
||||
##### The Time Conductor and Telemetry
|
||||
|
156
CONTRIBUTING.md
156
CONTRIBUTING.md
@ -103,7 +103,7 @@ the name chosen could not be mistaken for a topic or master branch.
|
||||
### Merging
|
||||
|
||||
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,
|
||||
and the pull request should include a completed author checklist, also
|
||||
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 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 request’s __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 request’s __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
|
||||
|
||||
Contributions to Open MCT are expected to meet the following standards.
|
||||
@ -131,96 +122,89 @@ changes.
|
||||
|
||||
### Code Standards
|
||||
|
||||
JavaScript sources in Open MCT must satisfy the ESLint rules defined in
|
||||
this repository. This is verified by the command line build.
|
||||
JavaScript sources in Open MCT must satisfy JSLint under its default
|
||||
settings. This is verified by the command line build.
|
||||
|
||||
#### Code Guidelines
|
||||
|
||||
JavaScript sources in Open MCT should:
|
||||
|
||||
1. Write clean code. Here’s a good summary - https://github.com/ryanmcdermott/clean-code-javascript.
|
||||
1. Include JSDoc for any exposed API (e.g. public methods, classes).
|
||||
1. Include non-JSDoc comments as-needed for explaining private variables,
|
||||
methods, or algorithms when they are non-obvious. Otherwise code
|
||||
should be self-documenting.
|
||||
1. Classes and Vue components should use camel case, first letter capitalized
|
||||
* Use four spaces for indentation. Tabs should not be used.
|
||||
* Include JSDoc for any exposed API (e.g. public methods, constructors).
|
||||
* Include non-JSDoc comments as-needed for explaining private variables,
|
||||
methods, or algorithms when they are non-obvious.
|
||||
* Define one public class per script, expressed as a constructor function
|
||||
returned from an AMD-style module.
|
||||
* Follow “Java-like” naming conventions. These includes:
|
||||
* Classes should use camel case, first letter capitalized
|
||||
(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).
|
||||
1. Source files that export functions should use camelCase, first letter lower-case (eg. testTools.js)
|
||||
1. Constants (variables or fields which are meant to be declared and
|
||||
* Constants (variables or fields which are meant to be declared and
|
||||
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
|
||||
1. File names should be the name of the exported class, plus a .js extension
|
||||
letters, with underscores between words (e.g. SOME_CONSTANT).
|
||||
* File names should be the name of the exported class, plus a .js extension
|
||||
(e.g. SomeClassName.js).
|
||||
1. Avoid anonymous functions, except when functions are short (one or two lines)
|
||||
and 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.
|
||||
1. Named functions are preferred over functions assigned to variables.
|
||||
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
|
||||
* Avoid anonymous functions, except when functions are short (a few lines)
|
||||
and/or their inclusion makes sense within the flow of the code
|
||||
(e.g. as arguments to a forEach call).
|
||||
* Avoid deep nesting (especially of functions), except where necessary
|
||||
(e.g. due to closure scope).
|
||||
1. End with a single new-line character.
|
||||
1. Always use ES6 `Class`es and inheritence rather than the pre-ES6 prototypal
|
||||
pattern.
|
||||
1. Within a given function's scope, do not mix declarations and imperative
|
||||
* End with a single new-line character.
|
||||
* Expose public methods by declaring them on the class's prototype.
|
||||
* Within a given function's scope, do not mix declarations and imperative
|
||||
code, and present these in the following order:
|
||||
* First, variable declarations and initialization.
|
||||
* Secondly, imperative statements.
|
||||
* Finally, the returned value. Functions should only have a single return statement.
|
||||
1. Avoid the use of "magic" values.
|
||||
eg.
|
||||
```JavaScript
|
||||
Const UNAUTHORIZED = 401
|
||||
if (responseCode === UNAUTHORIZED)
|
||||
```
|
||||
is preferable to
|
||||
```JavaScript
|
||||
if (responseCode === 401)
|
||||
```
|
||||
1. Don’t use the ternary operator. Yes it's terse, but there's probably a clearer way of writing it.
|
||||
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
|
||||
```
|
||||
* Second, function declarations.
|
||||
* Third, imperative statements.
|
||||
* Finally, the returned value.
|
||||
|
||||
Deviations from Open MCT code style guidelines require two-party agreement,
|
||||
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
|
||||
|
||||
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?
|
||||
3. Command line build passes?
|
||||
4. Changes have been smoke-tested?
|
||||
5. Testing instructions included?
|
||||
|
||||
### Reviewer Checklist
|
||||
|
||||
@ -316,4 +299,3 @@ checklist).
|
||||
2. Appropriate unit tests included?
|
||||
3. Code style and in-line documentation are appropriate?
|
||||
4. Commit messages meet standards?
|
||||
5. Has associated issue been labelled `unverified`? (only applicable if this PR closes the issue)
|
||||
|
@ -50,8 +50,7 @@ define([
|
||||
values: [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
format: "string"
|
||||
name: "Name"
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
@ -100,7 +99,7 @@ define([
|
||||
};
|
||||
|
||||
GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) {
|
||||
return Object.assign(
|
||||
return _.extend(
|
||||
{},
|
||||
domainObject.telemetry,
|
||||
METADATA_BY_TYPE[domainObject.type]
|
||||
|
@ -52,7 +52,6 @@ define([
|
||||
return {
|
||||
name: name,
|
||||
utc: Math.floor(timestamp / 5000) * 5000,
|
||||
local: Math.floor(timestamp / 5000) * 5000,
|
||||
url: IMAGE_SAMPLES[Math.floor(timestamp / 5000) % IMAGE_SAMPLES.length]
|
||||
};
|
||||
}
|
||||
@ -79,7 +78,7 @@ define([
|
||||
},
|
||||
request: function (domainObject, options) {
|
||||
var start = options.start;
|
||||
var end = Math.min(options.end, Date.now());
|
||||
var end = options.end;
|
||||
var data = [];
|
||||
while (start <= end && data.length < 5000) {
|
||||
data.push(pointForTimestamp(start, domainObject.name));
|
||||
@ -119,14 +118,6 @@ define([
|
||||
name: 'Time',
|
||||
key: 'utc',
|
||||
format: 'utc',
|
||||
hints: {
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Local Time',
|
||||
key: 'local',
|
||||
format: 'local-format',
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="example">{{ msg }}</div>
|
||||
<div class="example">{{ msg }}</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Hello world!'
|
||||
}
|
||||
|
@ -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
|
||||
Administration. All rights reserved.
|
||||
|
||||
@ -43,9 +43,9 @@
|
||||
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.LocalStorage());
|
||||
openmct.install(openmct.plugins.Generator());
|
||||
openmct.install(openmct.plugins.ExampleImagery());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
|
@ -24,27 +24,16 @@
|
||||
|
||||
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) => {
|
||||
const webpackConfig = require('./webpack.config.js');
|
||||
delete webpackConfig.output;
|
||||
|
||||
if (!devMode || coverageEnabled) {
|
||||
if (!devMode) {
|
||||
webpackConfig.module.rules.push({
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules|example|lib|dist/,
|
||||
use: {
|
||||
loader: 'istanbul-instrumenter-loader',
|
||||
options: {
|
||||
esModules: true
|
||||
}
|
||||
}
|
||||
exclude: /node_modules|example/,
|
||||
use: 'istanbul-instrumenter-loader'
|
||||
});
|
||||
}
|
||||
|
||||
@ -56,7 +45,11 @@ module.exports = (config) => {
|
||||
'src/**/*Spec.js'
|
||||
],
|
||||
port: 9876,
|
||||
reporters: reporters,
|
||||
reporters: [
|
||||
'progress',
|
||||
'coverage',
|
||||
'html'
|
||||
],
|
||||
browsers: browsers,
|
||||
customLaunchers: {
|
||||
ChromeDebugging: {
|
||||
@ -68,27 +61,27 @@ module.exports = (config) => {
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
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.
|
||||
htmlReporter: {
|
||||
outputDir: "dist/reports/tests",
|
||||
preserveDescribeNesting: true,
|
||||
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: {
|
||||
'platform/**/*Spec.js': ['webpack', 'sourcemap'],
|
||||
'src/**/*Spec.js': ['webpack', 'sourcemap']
|
||||
// add webpack as preprocessor
|
||||
'platform/**/*Spec.js': [ 'webpack', 'sourcemap' ],
|
||||
'src/**/*Spec.js': [ 'webpack', 'sourcemap' ]
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
|
29
package.json
29
package.json
@ -2,8 +2,10 @@
|
||||
"name": "openmct",
|
||||
"version": "1.0.0-snapshot",
|
||||
"description": "The Open MCT core platform",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"angular": "1.7.9",
|
||||
"acorn": "6.2.0",
|
||||
"angular": "1.4.14",
|
||||
"angular-route": "1.4.14",
|
||||
"babel-eslint": "8.2.6",
|
||||
"comma-separated-values": "^3.6.4",
|
||||
@ -23,7 +25,6 @@
|
||||
"d3-time-format": "2.1.x",
|
||||
"eslint": "5.2.0",
|
||||
"eslint-plugin-vue": "^6.0.0",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0",
|
||||
"eventemitter3": "^1.2.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"express": "^4.13.1",
|
||||
@ -38,28 +39,26 @@
|
||||
"istanbul-instrumenter-loader": "^3.0.1",
|
||||
"jasmine-core": "^3.1.0",
|
||||
"jsdoc": "^3.3.2",
|
||||
"karma": "5.0.9",
|
||||
"karma-chrome-launcher": "3.1.0",
|
||||
"karma": "^2.0.3",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-cli": "^1.0.1",
|
||||
"karma-coverage": "^1.1.2",
|
||||
"karma-coverage-istanbul-reporter": "^2.1.1",
|
||||
"karma-html-reporter": "^0.2.7",
|
||||
"karma-jasmine": "^2.0.0",
|
||||
"karma-jasmine": "^1.1.2",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-webpack": "^3.0.0",
|
||||
"location-bar": "^3.0.1",
|
||||
"lodash": "^4.17.12",
|
||||
"lodash": "^3.10.1",
|
||||
"markdown-toc": "^0.11.7",
|
||||
"marked": "^0.3.5",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
"minimist": "^1.1.1",
|
||||
"moment": "2.25.3",
|
||||
"moment": "^2.11.1",
|
||||
"moment-duration-format": "^2.2.2",
|
||||
"moment-timezone": "0.5.28",
|
||||
"moment-timezone": "^0.5.21",
|
||||
"node-bourbon": "^4.2.3",
|
||||
"node-sass": "^4.9.2",
|
||||
"painterro": "^0.2.65",
|
||||
"plotly.js": "^1.54.1",
|
||||
"printj": "^1.2.1",
|
||||
"raw-loader": "^0.5.1",
|
||||
"request": "^2.69.0",
|
||||
@ -77,16 +76,14 @@
|
||||
"zepto": "^1.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rm -rf ./dist",
|
||||
"start": "node app.js",
|
||||
"lint": "eslint platform example src --ext .js,.vue openmct.js",
|
||||
"lint:fix": "eslint platform example src --ext .js,.vue openmct.js --fix",
|
||||
"lint": "eslint platform example src/**/*.{js,vue} openmct.js",
|
||||
"lint:fix": "eslint platform example src/**/*.{js,vue} openmct.js --fix",
|
||||
"build:prod": "cross-env NODE_ENV=production webpack",
|
||||
"build:dev": "webpack",
|
||||
"build:watch": "webpack --watch",
|
||||
"test": "cross-env NODE_OPTIONS=\"--max-old-space-size=4096\" karma start --single-run",
|
||||
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
|
||||
"test:coverage": "cross-env NODE_ENV=production COVERAGE=true 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",
|
||||
"verify": "concurrently 'npm:test' 'npm:lint'",
|
||||
"jsdoc": "jsdoc -c jsdoc.json -R API.md -r -d dist/docs/api",
|
||||
|
@ -6,12 +6,6 @@
|
||||
ng-show="ngModel.dialog.messages.length > 1 ||
|
||||
ngModel.dialog.messages.length == 0">s</span>
|
||||
</div>
|
||||
<button
|
||||
ng-if="ngModel.dialog.topBarButton"
|
||||
class="c-button c-button--major"
|
||||
ng-click="ngModel.topBarButton.onClick">
|
||||
{{ ngModel.topBarButton.label }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="w-messages c-overlay__messages">
|
||||
<mct-include
|
||||
@ -22,7 +16,7 @@
|
||||
<button ng-repeat="dialogAction in ngModel.dialog.actions"
|
||||
class="c-button c-button--major"
|
||||
ng-click="dialogAction.action()">
|
||||
{{ dialogAction.label }}
|
||||
{{dialogAction.label}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['objectUtils'],
|
||||
['../../../../../src/api/objects/object-utils'],
|
||||
function (objectUtils) {
|
||||
|
||||
/**
|
||||
|
@ -21,15 +21,44 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
"./src/NotificationService"
|
||||
"./src/NotificationIndicatorController",
|
||||
"./src/NotificationIndicator",
|
||||
"./src/NotificationService",
|
||||
"./res/notification-indicator.html"
|
||||
], function (
|
||||
NotificationService
|
||||
NotificationIndicatorController,
|
||||
NotificationIndicator,
|
||||
NotificationService,
|
||||
notificationIndicatorTemplate
|
||||
) {
|
||||
|
||||
return {
|
||||
name:"platform/commonUI/notification",
|
||||
definition: {
|
||||
"extensions": {
|
||||
"templates": [
|
||||
{
|
||||
"key": "notificationIndicatorTemplate",
|
||||
"template": notificationIndicatorTemplate
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "NotificationIndicatorController",
|
||||
"implementation": NotificationIndicatorController,
|
||||
"depends": [
|
||||
"$scope",
|
||||
"openmct",
|
||||
"dialogService"
|
||||
]
|
||||
}
|
||||
],
|
||||
"indicators": [
|
||||
{
|
||||
"implementation": NotificationIndicator,
|
||||
"priority": "fallback"
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"key": "notificationService",
|
||||
|
@ -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 c-indicator__label">
|
||||
<button ng-click="showNotificationsList()">
|
||||
{{notifications.length}} Notification<span ng-show="notifications.length > 1">s</span></button>
|
||||
</span><span class="c-indicator__count">{{notifications.length}}</span>
|
||||
</div>
|
@ -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
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@ -19,25 +19,15 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import Vue from 'vue';
|
||||
import NotificationIndicator from './components/NotificationIndicator.vue';
|
||||
|
||||
export default function plugin() {
|
||||
return function install(openmct) {
|
||||
let component = new Vue ({
|
||||
provide: {
|
||||
openmct
|
||||
},
|
||||
components: {
|
||||
NotificationIndicator: NotificationIndicator
|
||||
},
|
||||
template: '<NotificationIndicator></NotificationIndicator>'
|
||||
}),
|
||||
indicator = {
|
||||
key: 'notifications-indicator',
|
||||
element: component.$mount().$el
|
||||
};
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
openmct.indicators.add(indicator);
|
||||
};
|
||||
}
|
||||
function NotificationIndicator() {}
|
||||
|
||||
NotificationIndicator.template = 'notificationIndicatorTemplate';
|
||||
|
||||
return NotificationIndicator;
|
||||
}
|
||||
);
|
@ -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;
|
||||
}
|
||||
);
|
||||
|
@ -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) {
|
||||
|
||||
xdescribe("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();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -26,7 +26,7 @@
|
||||
* @namespace platform/containment
|
||||
*/
|
||||
define(
|
||||
['objectUtils'],
|
||||
['../../../src/api/objects/object-utils'],
|
||||
function (objectUtils) {
|
||||
|
||||
function PersistableCompositionPolicy(openmct) {
|
||||
|
@ -81,7 +81,7 @@ define(
|
||||
baseContext = context || {};
|
||||
}
|
||||
|
||||
var actionContext = Object.assign({}, baseContext);
|
||||
var actionContext = _.extend({}, baseContext);
|
||||
actionContext.domainObject = this.domainObject;
|
||||
|
||||
return this.actionService.getActions(actionContext);
|
||||
|
@ -87,11 +87,6 @@ define([
|
||||
bootstrapper
|
||||
);
|
||||
|
||||
// Override of angular1.6 ! hashPrefix
|
||||
app.config(['$locationProvider', function ($locationProvider) {
|
||||
$locationProvider.hashPrefix('');
|
||||
}]);
|
||||
|
||||
// Apply logging levels; this must be done now, before the
|
||||
// first log statement.
|
||||
new LogLevel(logLevel).configure(app, $log);
|
||||
|
@ -121,7 +121,7 @@ define(['lodash'], function (_) {
|
||||
*/
|
||||
ExportAsJSONAction.prototype.rewriteLink = function (child, parent) {
|
||||
this.externalIdentifiers.push(this.getId(child));
|
||||
var index = parent.composition.findIndex(id => {
|
||||
var index = _.findIndex(parent.composition, function (id) {
|
||||
return _.isEqual(child.identifier, id);
|
||||
});
|
||||
var copyOfChild = this.copyObject(child);
|
||||
|
@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
define(['zepto', 'objectUtils'], function ($, objectUtils) {
|
||||
define(['zepto', '../../../../src/api/objects/object-utils.js'], function ($, objectUtils) {
|
||||
|
||||
/**
|
||||
* The ImportAsJSONAction is available from context menus and allows a user
|
||||
|
@ -71,7 +71,7 @@ define([
|
||||
},
|
||||
{
|
||||
"key": "ELASTIC_PATH",
|
||||
"value": "mct/_doc",
|
||||
"value": "mct/domain_object",
|
||||
"priority": "fallback"
|
||||
},
|
||||
{
|
||||
|
@ -32,9 +32,9 @@ define(
|
||||
// JSLint doesn't like underscore-prefixed properties,
|
||||
// so hide them here.
|
||||
var SRC = "_source",
|
||||
CONFLICT = 409,
|
||||
SEQ_NO = "_seq_no",
|
||||
PRIMARY_TERM = "_primary_term";
|
||||
REV = "_version",
|
||||
ID = "_id",
|
||||
CONFLICT = 409;
|
||||
|
||||
/**
|
||||
* The ElasticPersistenceProvider reads and writes JSON documents
|
||||
@ -104,8 +104,7 @@ define(
|
||||
// Get a domain object model out of ElasticSearch's response
|
||||
ElasticPersistenceProvider.prototype.getModel = function (response) {
|
||||
if (response && response[SRC]) {
|
||||
this.revs[response[SEQ_NO]] = response[SEQ_NO];
|
||||
this.revs[response[PRIMARY_TERM]] = response[PRIMARY_TERM];
|
||||
this.revs[response[ID]] = response[REV];
|
||||
return response[SRC];
|
||||
} else {
|
||||
return undefined;
|
||||
@ -117,8 +116,7 @@ define(
|
||||
// indicate that the request failed.
|
||||
ElasticPersistenceProvider.prototype.checkResponse = function (response, key) {
|
||||
if (response && !response.error) {
|
||||
this.revs[SEQ_NO] = response[SEQ_NO];
|
||||
this.revs[PRIMARY_TERM] = response[PRIMARY_TERM];
|
||||
this.revs[key] = response[REV];
|
||||
return response;
|
||||
} else {
|
||||
return this.handleError(response, key);
|
||||
@ -149,7 +147,7 @@ define(
|
||||
function checkUpdate(response) {
|
||||
return self.checkResponse(response, key);
|
||||
}
|
||||
return this.put(key, value)
|
||||
return this.put(key, value, { version: this.revs[key] })
|
||||
.then(checkUpdate);
|
||||
};
|
||||
|
||||
|
@ -85,7 +85,7 @@ define(
|
||||
it("allows object creation", function () {
|
||||
var model = { someKey: "some value" };
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_seq_no": 1, "_primary_term": 1 }
|
||||
data: { "_id": "abc", "_version": 1 }
|
||||
}));
|
||||
provider.createObject("testSpace", "abc", model).then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
@ -100,7 +100,7 @@ define(
|
||||
it("allows object models to be read back", function () {
|
||||
var model = { someKey: "some value" };
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_seq_no": 1, "_primary_term": 1, "_source": model }
|
||||
data: { "_id": "abc", "_version": 1, "_source": model }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc").then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
@ -117,19 +117,19 @@ define(
|
||||
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_source": {} }
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
// Now perform an update
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_seq_no": 1, "_source": {} }
|
||||
data: { "_id": "abc", "_version": 43, "_source": {} }
|
||||
}));
|
||||
provider.updateObject("testSpace", "abc", model).then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
url: "/test/db/abc",
|
||||
method: "PUT",
|
||||
params: undefined,
|
||||
params: { version: 42 },
|
||||
data: model
|
||||
});
|
||||
expect(capture.calls.mostRecent().args[0]).toBeTruthy();
|
||||
@ -138,13 +138,13 @@ define(
|
||||
it("allows object deletion", function () {
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_source": {} }
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
// Now perform an update
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_source": {} }
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
}));
|
||||
provider.deleteObject("testSpace", "abc", {}).then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
@ -167,13 +167,13 @@ define(
|
||||
expect(capture).toHaveBeenCalledWith(undefined);
|
||||
});
|
||||
|
||||
it("handles rejection due to _seq_no", function () {
|
||||
it("handles rejection due to version", function () {
|
||||
var model = { someKey: "some value" },
|
||||
mockErrorCallback = jasmine.createSpy('error');
|
||||
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_seq_no": 1, "_source": {} }
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
@ -196,7 +196,7 @@ define(
|
||||
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_seq_no": 1, "_source": {} }
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* Module defining GenericSearchProvider. Created by shale on 07/16/2015.
|
||||
*/
|
||||
define([
|
||||
'objectUtils',
|
||||
'../../../../src/api/objects/object-utils',
|
||||
'lodash'
|
||||
], function (
|
||||
objectUtils,
|
||||
@ -191,7 +191,7 @@ define([
|
||||
}
|
||||
|
||||
var domainObject = objectUtils.toNewFormat(model, id);
|
||||
var composition = this.openmct.composition.registry.find(p => {
|
||||
var composition = _.find(this.openmct.composition.registry, function (p) {
|
||||
return p.appliesTo(domainObject);
|
||||
});
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
define(
|
||||
[
|
||||
'objectUtils',
|
||||
'../../../src/api/objects/object-utils',
|
||||
'lodash'
|
||||
],
|
||||
function (
|
||||
@ -235,7 +235,7 @@ define(
|
||||
var defaultRange = metadata.valuesForHints(['range'])[0];
|
||||
defaultRange = defaultRange ? defaultRange.key : undefined;
|
||||
|
||||
var sourceMap = _.keyBy(metadata.values(), 'key');
|
||||
var sourceMap = _.indexBy(metadata.values(), 'key');
|
||||
|
||||
var isLegacyProvider = telemetryAPI.findRequestProvider(domainObject) ===
|
||||
telemetryAPI.legacyProvider;
|
||||
@ -300,7 +300,7 @@ define(
|
||||
var defaultRange = metadata.valuesForHints(['range'])[0];
|
||||
defaultRange = defaultRange ? defaultRange.key : undefined;
|
||||
|
||||
var sourceMap = _.keyBy(metadata.values(), 'key');
|
||||
var sourceMap = _.indexBy(metadata.values(), 'key');
|
||||
|
||||
var isLegacyProvider = telemetryAPI.findSubscriptionProvider(domainObject) ===
|
||||
telemetryAPI.legacyProvider;
|
||||
|
18
src/MCT.js
18
src/MCT.js
@ -28,7 +28,7 @@ define([
|
||||
'./api/api',
|
||||
'./api/overlays/OverlayAPI',
|
||||
'./selection/Selection',
|
||||
'objectUtils',
|
||||
'./api/objects/object-utils',
|
||||
'./plugins/plugins',
|
||||
'./adapter/indicators/legacy-indicators-plugin',
|
||||
'./plugins/buildInfo/plugin',
|
||||
@ -249,7 +249,7 @@ define([
|
||||
this.legacyRegistry = new BundleRegistry();
|
||||
installDefaultBundles(this.legacyRegistry);
|
||||
|
||||
// Plugins that are installed by default
|
||||
// Plugin's that are installed by default
|
||||
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
@ -266,7 +266,6 @@ define([
|
||||
this.install(this.plugins.WebPage());
|
||||
this.install(this.plugins.Condition());
|
||||
this.install(this.plugins.ConditionWidget());
|
||||
this.install(this.plugins.NotificationIndicator());
|
||||
}
|
||||
|
||||
MCT.prototype = Object.create(EventEmitter.prototype);
|
||||
@ -351,13 +350,17 @@ define([
|
||||
* @param {HTMLElement} [domElement] the DOM element in which to run
|
||||
* MCT; if undefined, MCT will be run in the body of the document
|
||||
*/
|
||||
MCT.prototype.start = function (domElement = document.body, isHeadlessMode = false) {
|
||||
MCT.prototype.start = function (domElement) {
|
||||
if (!this.plugins.DisplayLayout._installed) {
|
||||
this.install(this.plugins.DisplayLayout({
|
||||
showAsView: ['summary-widget']
|
||||
}));
|
||||
}
|
||||
|
||||
if (!domElement) {
|
||||
domElement = document.body;
|
||||
}
|
||||
|
||||
this.element = domElement;
|
||||
|
||||
this.legacyExtension('runs', {
|
||||
@ -397,7 +400,6 @@ define([
|
||||
// something has depended upon objectService. Cool, right?
|
||||
this.$injector.get('objectService');
|
||||
|
||||
if (!isHeadlessMode) {
|
||||
var appLayout = new Vue({
|
||||
components: {
|
||||
'Layout': Layout.default
|
||||
@ -411,17 +413,11 @@ define([
|
||||
|
||||
this.layout = appLayout.$refs.layout;
|
||||
Browse(this);
|
||||
}
|
||||
this.router.start();
|
||||
this.emit('start');
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
MCT.prototype.startHeadless = function () {
|
||||
let unreachableNode = document.createElement('div');
|
||||
return this.start(unreachableNode, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a plugin in MCT.
|
||||
*
|
||||
|
@ -21,11 +21,11 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'./MCT',
|
||||
'./plugins/plugins',
|
||||
'legacyRegistry',
|
||||
'testUtils'
|
||||
], function (plugins, legacyRegistry, testUtils) {
|
||||
describe("MCT", function () {
|
||||
'legacyRegistry'
|
||||
], function (MCT, plugins, legacyRegistry) {
|
||||
xdescribe("MCT", function () {
|
||||
var openmct;
|
||||
var mockPlugin;
|
||||
var mockPlugin2;
|
||||
@ -38,7 +38,7 @@ define([
|
||||
mockListener = jasmine.createSpy('listener');
|
||||
oldBundles = legacyRegistry.list();
|
||||
|
||||
openmct = testUtils.createOpenMct();
|
||||
openmct = new MCT();
|
||||
|
||||
openmct.install(mockPlugin);
|
||||
openmct.install(mockPlugin2);
|
||||
@ -63,11 +63,8 @@ define([
|
||||
});
|
||||
|
||||
describe("start", function () {
|
||||
let appHolder;
|
||||
beforeEach(function (done) {
|
||||
appHolder = document.createElement("div");
|
||||
openmct.on('start', done);
|
||||
openmct.start(appHolder);
|
||||
beforeEach(function () {
|
||||
openmct.start();
|
||||
});
|
||||
|
||||
it("calls plugins for configuration", function () {
|
||||
@ -78,51 +75,25 @@ define([
|
||||
it("emits a start event", function () {
|
||||
expect(mockListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Renders the application into the provided container element", function () {
|
||||
let openMctShellElements = appHolder.querySelectorAll('div.l-shell');
|
||||
expect(openMctShellElements.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("startHeadless", function () {
|
||||
beforeEach(function (done) {
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
it("calls plugins for configuration", function () {
|
||||
expect(mockPlugin).toHaveBeenCalledWith(openmct);
|
||||
expect(mockPlugin2).toHaveBeenCalledWith(openmct);
|
||||
});
|
||||
|
||||
it("emits a start event", function () {
|
||||
expect(mockListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Does not render Open MCT", function () {
|
||||
let openMctShellElements = document.body.querySelectorAll('div.l-shell');
|
||||
expect(openMctShellElements.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setAssetPath", function () {
|
||||
var testAssetPath;
|
||||
|
||||
beforeEach(function () {
|
||||
openmct.legacyExtension = jasmine.createSpy('legacyExtension');
|
||||
});
|
||||
|
||||
it("configures the path for assets", function () {
|
||||
testAssetPath = "some/path/";
|
||||
openmct.setAssetPath(testAssetPath);
|
||||
expect(openmct.getAssetPath()).toBe(testAssetPath);
|
||||
});
|
||||
|
||||
it("adds a trailing /", function () {
|
||||
testAssetPath = "some/path";
|
||||
openmct.legacyExtension = jasmine.createSpy('legacyExtension');
|
||||
openmct.setAssetPath(testAssetPath);
|
||||
expect(openmct.getAssetPath()).toBe(testAssetPath + "/");
|
||||
});
|
||||
|
||||
it("internally configures the path for assets", function () {
|
||||
expect(openmct.legacyExtension).toHaveBeenCalledWith(
|
||||
'constants',
|
||||
{
|
||||
key: "ASSETS_PATH",
|
||||
value: testAssetPath
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'objectUtils'
|
||||
'../../api/objects/object-utils'
|
||||
], function (objectUtils) {
|
||||
function ActionDialogDecorator(mct, actionService) {
|
||||
this.mct = mct;
|
||||
|
@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(['objectUtils'], function (objectUtils) {
|
||||
define(['../../api/objects/object-utils'], function (objectUtils) {
|
||||
function AdapterCapability(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
* Module defining AlternateCompositionCapability. Created by vwoeltje on 11/7/14.
|
||||
*/
|
||||
define([
|
||||
'objectUtils',
|
||||
'../../api/objects/object-utils',
|
||||
'../../../platform/core/src/capabilities/ContextualDomainObject'
|
||||
], function (objectUtils, ContextualDomainObject) {
|
||||
function AlternateCompositionCapability($injector, domainObject) {
|
||||
|
@ -31,7 +31,6 @@ define([
|
||||
var capability = viewConstructor(domainObject);
|
||||
var oldInvoke = capability.invoke.bind(capability);
|
||||
|
||||
/* eslint-disable you-dont-need-lodash-underscore/map */
|
||||
capability.invoke = function () {
|
||||
var availableViews = oldInvoke();
|
||||
var newDomainObject = capability
|
||||
@ -53,8 +52,6 @@ define([
|
||||
.map('view')
|
||||
.value();
|
||||
};
|
||||
/* eslint-enable you-dont-need-lodash-underscore/map */
|
||||
|
||||
return capability;
|
||||
};
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
define([
|
||||
'../capabilities/AlternateCompositionCapability',
|
||||
'objectUtils'
|
||||
'../../api/objects/object-utils'
|
||||
], function (
|
||||
AlternateCompositionCapability,
|
||||
objectUtils
|
||||
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'objectUtils'
|
||||
'../../api/objects/object-utils'
|
||||
], function (
|
||||
utils
|
||||
) {
|
||||
|
@ -78,7 +78,7 @@ define([
|
||||
};
|
||||
|
||||
TimeSettingsURLHandler.prototype.parseQueryParams = function () {
|
||||
var searchParams = _.pick(this.$location.search(), Object.values(SEARCH));
|
||||
var searchParams = _.pick(this.$location.search(), _.values(SEARCH));
|
||||
var parsedParams = {
|
||||
clock: searchParams[SEARCH.MODE],
|
||||
timeSystem: searchParams[SEARCH.TIME_SYSTEM]
|
||||
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'objectUtils'
|
||||
'../../api/objects/object-utils'
|
||||
], function (
|
||||
utils
|
||||
) {
|
||||
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'objectUtils'
|
||||
'../../api/objects/object-utils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
define([
|
||||
'./LegacyViewProvider',
|
||||
'./TypeInspectorViewProvider',
|
||||
'objectUtils'
|
||||
'../../api/objects/object-utils'
|
||||
], function (
|
||||
LegacyViewProvider,
|
||||
TypeInspectorViewProvider,
|
||||
|
@ -70,7 +70,7 @@ define([
|
||||
* @memberof module:openmct.CompositionAPI#
|
||||
*/
|
||||
CompositionAPI.prototype.get = function (domainObject) {
|
||||
var provider = this.registry.find(p => {
|
||||
var provider = _.find(this.registry, function (p) {
|
||||
return p.appliesTo(domainObject);
|
||||
});
|
||||
|
||||
|
@ -122,7 +122,7 @@ define([
|
||||
throw new Error('Event not supported by composition: ' + event);
|
||||
}
|
||||
|
||||
var index = this.listeners[event].findIndex(l => {
|
||||
var index = _.findIndex(this.listeners[event], function (l) {
|
||||
return l.callback === callback && l.context === context;
|
||||
});
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
define([
|
||||
'lodash',
|
||||
'objectUtils'
|
||||
'../objects/object-utils'
|
||||
], function (
|
||||
_,
|
||||
objectUtils
|
||||
@ -143,7 +143,7 @@ define([
|
||||
var keyString = objectUtils.makeKeyString(domainObject.identifier);
|
||||
var objectListeners = this.listeningTo[keyString];
|
||||
|
||||
var index = objectListeners[event].findIndex(l => {
|
||||
var index = _.findIndex(objectListeners[event], function (l) {
|
||||
return l.callback === callback && l.context === context;
|
||||
});
|
||||
|
||||
@ -196,8 +196,8 @@ define([
|
||||
* @private
|
||||
*/
|
||||
DefaultCompositionProvider.prototype.includes = function (parent, childId) {
|
||||
return parent.composition.some(composee =>
|
||||
this.publicAPI.objects.areIdsEqual(composee, childId));
|
||||
return parent.composition.findIndex(composee =>
|
||||
this.publicAPI.objects.areIdsEqual(composee, childId)) !== -1;
|
||||
};
|
||||
|
||||
DefaultCompositionProvider.prototype.reorder = function (domainObject, oldIndex, newIndex) {
|
||||
|
@ -128,11 +128,6 @@ export default class NotificationAPI extends EventEmitter {
|
||||
return this._notify(notificationModel);
|
||||
}
|
||||
|
||||
dismissAllNotifications() {
|
||||
this.notifications = [];
|
||||
this.emit('dismiss-all');
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimize a notification. The notification will still be available
|
||||
* from the notification list. Typically notifications with a
|
||||
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'objectUtils',
|
||||
'./object-utils.js',
|
||||
'lodash'
|
||||
], function (
|
||||
utils,
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
define([
|
||||
'lodash',
|
||||
'objectUtils',
|
||||
'./object-utils',
|
||||
'./MutableObject',
|
||||
'./RootRegistry',
|
||||
'./RootObjectProvider',
|
||||
|
@ -43,7 +43,7 @@ define([
|
||||
}
|
||||
|
||||
RootRegistry.prototype.addRoot = function (key) {
|
||||
if (isKey(key) || (Array.isArray(key) && key.every(isKey))) {
|
||||
if (isKey(key) || (_.isArray(key) && _.every(key, isKey))) {
|
||||
this.providers.push(function () {
|
||||
return key;
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
define([
|
||||
'objectUtils'
|
||||
'../object-utils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
|
@ -85,9 +85,9 @@ define([
|
||||
value: +e.value
|
||||
};
|
||||
}), 'e.value');
|
||||
valueMetadata.values = valueMetadata.enumerations.map(e => e.value);
|
||||
valueMetadata.max = Math.max(valueMetadata.values);
|
||||
valueMetadata.min = Math.min(valueMetadata.values);
|
||||
valueMetadata.values = _.pluck(valueMetadata.enumerations, 'value');
|
||||
valueMetadata.max = _.max(valueMetadata.values);
|
||||
valueMetadata.min = _.min(valueMetadata.values);
|
||||
}
|
||||
|
||||
valueMetadatas.push(valueMetadata);
|
||||
@ -103,7 +103,7 @@ define([
|
||||
var metadata = domainObject.telemetry || {};
|
||||
if (this.typeHasTelemetry(domainObject)) {
|
||||
var typeMetadata = this.typeService.getType(domainObject.type).typeDef.telemetry;
|
||||
Object.assign(metadata, typeMetadata);
|
||||
_.extend(metadata, typeMetadata);
|
||||
if (!metadata.values) {
|
||||
metadata.values = valueMetadatasFromOldFormat(metadata);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ define([
|
||||
'./TelemetryMetadataManager',
|
||||
'./TelemetryValueFormatter',
|
||||
'./DefaultMetadataProvider',
|
||||
'objectUtils',
|
||||
'../objects/object-utils',
|
||||
'lodash'
|
||||
], function (
|
||||
TelemetryMetadataManager,
|
||||
@ -370,7 +370,7 @@ define([
|
||||
TelemetryAPI.prototype.commonValuesForHints = function (metadatas, hints) {
|
||||
var options = metadatas.map(function (metadata) {
|
||||
var values = metadata.valuesForHints(hints);
|
||||
return _.keyBy(values, 'key');
|
||||
return _.indexBy(values, 'key');
|
||||
}).reduce(function (a, b) {
|
||||
var results = {};
|
||||
Object.keys(a).forEach(function (key) {
|
||||
@ -383,7 +383,7 @@ define([
|
||||
var sortKeys = hints.map(function (h) {
|
||||
return 'hints.' + h;
|
||||
});
|
||||
return _.sortBy(options, sortKeys);
|
||||
return _.sortByAll(options, sortKeys);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -57,13 +57,13 @@ define([
|
||||
|
||||
if (valueMetadata.format === 'enum') {
|
||||
if (!valueMetadata.values) {
|
||||
valueMetadata.values = valueMetadata.enumerations.map(e => e.value);
|
||||
valueMetadata.values = _.pluck(valueMetadata.enumerations, 'value');
|
||||
}
|
||||
if (!valueMetadata.hasOwnProperty('max')) {
|
||||
valueMetadata.max = Math.max(valueMetadata.values) + 1;
|
||||
valueMetadata.max = _.max(valueMetadata.values) + 1;
|
||||
}
|
||||
if (!valueMetadata.hasOwnProperty('min')) {
|
||||
valueMetadata.min = Math.min(valueMetadata.values) - 1;
|
||||
valueMetadata.min = _.min(valueMetadata.values) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ define([
|
||||
return metadata.hints[hint];
|
||||
}
|
||||
});
|
||||
return _.sortBy(matchingMetadata, ...iteratees);
|
||||
return _.sortByAll(matchingMetadata, ...iteratees);
|
||||
};
|
||||
|
||||
TelemetryMetadataManager.prototype.getFilterableValues = function () {
|
||||
|
@ -75,7 +75,7 @@ export default {
|
||||
this.items.push(item);
|
||||
},
|
||||
removeItem(identifier) {
|
||||
let index = this.items.findIndex(item => this.openmct.objects.makeKeyString(identifier) === item.key);
|
||||
let index = _.findIndex(this.items, (item) => this.openmct.objects.makeKeyString(identifier) === item.key);
|
||||
|
||||
this.items.splice(index, 1);
|
||||
},
|
||||
|
@ -102,7 +102,7 @@ export default {
|
||||
this.compositions.push({composition, addCallback, removeCallback});
|
||||
},
|
||||
removePrimary(identifier) {
|
||||
let index = this.primaryTelemetryObjects.findIndex(primary => this.openmct.objects.makeKeyString(identifier) === primary.key),
|
||||
let index = _.findIndex(this.primaryTelemetryObjects, (primary) => this.openmct.objects.makeKeyString(identifier) === primary.key),
|
||||
primary = this.primaryTelemetryObjects[index];
|
||||
|
||||
this.$set(this.secondaryTelemetryObjects, primary.key, undefined);
|
||||
@ -130,7 +130,7 @@ export default {
|
||||
removeSecondary(primary) {
|
||||
return (identifier) => {
|
||||
let array = this.secondaryTelemetryObjects[primary.key],
|
||||
index = array.findIndex(secondary => this.openmct.objects.makeKeyString(identifier) === secondary.key);
|
||||
index = _.findIndex(array, (secondary) => this.openmct.objects.makeKeyString(identifier) === secondary.key);
|
||||
|
||||
array.splice(index, 1);
|
||||
|
||||
|
@ -69,9 +69,9 @@ export default class ConditionClass extends EventEmitter {
|
||||
console.log('no data received');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isTelemetryUsed(datum.id)) {
|
||||
|
||||
if (!this.isTelemetryUsed(datum.id)) {
|
||||
return;
|
||||
}
|
||||
this.criteria.forEach(criterion => {
|
||||
if (this.isAnyOrAllTelemetry(criterion)) {
|
||||
criterion.getResult(datum, this.conditionManager.telemetryObjects);
|
||||
@ -82,7 +82,6 @@ export default class ConditionClass extends EventEmitter {
|
||||
|
||||
this.result = evaluateResults(this.criteria.map(criterion => criterion.result), this.trigger);
|
||||
}
|
||||
}
|
||||
|
||||
isAnyOrAllTelemetry(criterion) {
|
||||
return (criterion.telemetry && (criterion.telemetry === 'all' || criterion.telemetry === 'any'));
|
||||
@ -207,7 +206,7 @@ export default class ConditionClass extends EventEmitter {
|
||||
let latestTimestamp;
|
||||
let criteriaResults = {};
|
||||
const criteriaRequests = this.criteria
|
||||
.map(criterion => criterion.requestLAD(this.conditionManager.telemetryObjects));
|
||||
.map(criterion => criterion.requestLAD({telemetryObjects: this.conditionManager.telemetryObjects}));
|
||||
|
||||
return Promise.all(criteriaRequests)
|
||||
.then(results => {
|
||||
|
@ -55,8 +55,9 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.telemetryObjects[id] = Object.assign({}, endpoint, {telemetryMetaData: this.openmct.telemetry.getMetadata(endpoint).valueMetadatas});
|
||||
this.subscriptions[id] = this.openmct.telemetry.subscribe(
|
||||
endpoint,
|
||||
this.telemetryReceived.bind(this, endpoint)
|
||||
this.telemetryReceived.bind(this, id)
|
||||
);
|
||||
// TODO check if this is needed
|
||||
this.updateConditionTelemetry();
|
||||
}
|
||||
|
||||
@ -70,7 +71,6 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
delete this.telemetryObjects[id];
|
||||
this.removeConditionTelemetry();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
@ -86,30 +86,6 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.conditionClassCollection.forEach((condition) => condition.updateTelemetry());
|
||||
}
|
||||
|
||||
removeConditionTelemetry() {
|
||||
let conditionsChanged = false;
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration) => {
|
||||
conditionConfiguration.configuration.criteria.forEach((criterion, index) => {
|
||||
const isAnyAllTelemetry = criterion.telemetry && (criterion.telemetry === 'any' || criterion.telemetry === 'all');
|
||||
if (!isAnyAllTelemetry) {
|
||||
const found = Object.values(this.telemetryObjects).find((telemetryObject) => {
|
||||
return this.openmct.objects.areIdsEqual(telemetryObject.identifier, criterion.telemetry);
|
||||
});
|
||||
if (!found) {
|
||||
criterion.telemetry = '';
|
||||
criterion.metadata = '';
|
||||
criterion.input = [];
|
||||
criterion.operation = '';
|
||||
conditionsChanged = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if (conditionsChanged) {
|
||||
this.persistConditions();
|
||||
}
|
||||
}
|
||||
|
||||
updateCondition(conditionConfiguration, index) {
|
||||
let condition = this.conditionClassCollection[index];
|
||||
condition.update(conditionConfiguration);
|
||||
@ -258,13 +234,9 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.openmct.time.timeSystem()
|
||||
);
|
||||
});
|
||||
|
||||
if (!Object.values(latestTimestamp).some(timeSystem => timeSystem)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const currentCondition = this.getCurrentConditionLAD(conditionResults);
|
||||
const currentOutput = Object.assign(
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
output: currentCondition.configuration.output,
|
||||
id: this.conditionSetDomainObject.identifier,
|
||||
@ -272,30 +244,12 @@ export default class ConditionManager extends EventEmitter {
|
||||
},
|
||||
latestTimestamp
|
||||
);
|
||||
|
||||
return [currentOutput];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isTelemetryUsed(endpoint) {
|
||||
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
||||
|
||||
for(const condition of this.conditionClassCollection) {
|
||||
if (condition.isTelemetryUsed(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
telemetryReceived(endpoint, datum) {
|
||||
if (!this.isTelemetryUsed(endpoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedDatum = this.createNormalizedDatum(datum, endpoint);
|
||||
telemetryReceived(id, datum) {
|
||||
const normalizedDatum = this.createNormalizedDatum(datum, id);
|
||||
const timeSystemKey = this.openmct.time.timeSystem().key;
|
||||
let timestamp = {};
|
||||
timestamp[timeSystemKey] = normalizedDatum[timeSystemKey];
|
||||
@ -329,11 +283,8 @@ export default class ConditionManager extends EventEmitter {
|
||||
return data;
|
||||
}
|
||||
|
||||
createNormalizedDatum(telemetryDatum, endpoint) {
|
||||
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
||||
const metadata = this.openmct.telemetry.getMetadata(endpoint).valueMetadatas;
|
||||
|
||||
const normalizedDatum = Object.values(metadata).reduce((datum, metadatum) => {
|
||||
createNormalizedDatum(telemetryDatum, id) {
|
||||
const normalizedDatum = Object.values(this.telemetryObjects[id].telemetryMetaData).reduce((datum, metadatum) => {
|
||||
const testValue = this.getTestData(metadatum);
|
||||
const formatter = this.openmct.telemetry.getValueFormatter(metadatum);
|
||||
datum[metadatum.key] = testValue !== undefined ? formatter.parse(testValue) : formatter.parse(telemetryDatum[metadatum.source]);
|
||||
|
@ -54,22 +54,13 @@ export default class ConditionSetMetadataProvider {
|
||||
return {
|
||||
values: this.getDomains().concat([
|
||||
{
|
||||
key: "state",
|
||||
source: "output",
|
||||
name: "State",
|
||||
format: "enum",
|
||||
name: 'Output',
|
||||
key: 'output',
|
||||
format: 'enum',
|
||||
enumerations: enumerations,
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "output",
|
||||
name: "Value",
|
||||
format: "string",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
}
|
||||
])
|
||||
};
|
||||
|
@ -45,7 +45,7 @@ export default class ConditionSetTelemetryProvider {
|
||||
|
||||
return conditionManager.requestLADConditionSetOutput()
|
||||
.then(latestOutput => {
|
||||
return latestOutput;
|
||||
return latestOutput ? [latestOutput] : [];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -47,24 +47,17 @@ describe("The condition", function () {
|
||||
name: "Test Object",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "value",
|
||||
name: "Value",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
key: "some-key",
|
||||
name: "Some attribute",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
}, {
|
||||
key: "testSource",
|
||||
source: "value",
|
||||
name: "Test",
|
||||
format: "string"
|
||||
key: "some-other-key",
|
||||
name: "Another attribute",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
@ -143,38 +136,4 @@ describe("The condition", function () {
|
||||
expect(result).toBeTrue();
|
||||
expect(conditionObj.criteria.length).toEqual(0);
|
||||
});
|
||||
|
||||
it("gets the result of a condition when new telemetry data is received", function () {
|
||||
conditionObj.getResult({
|
||||
value: '0',
|
||||
utc: 'Hi',
|
||||
id: testTelemetryObject.identifier.key
|
||||
});
|
||||
expect(conditionObj.result).toBeTrue();
|
||||
});
|
||||
|
||||
it("gets the result of a condition when new telemetry data is received", function () {
|
||||
conditionObj.getResult({
|
||||
value: '1',
|
||||
utc: 'Hi',
|
||||
id: testTelemetryObject.identifier.key
|
||||
});
|
||||
expect(conditionObj.result).toBeFalse();
|
||||
});
|
||||
|
||||
it("keeps the old result new telemetry data is not used by it", function () {
|
||||
conditionObj.getResult({
|
||||
value: '0',
|
||||
utc: 'Hi',
|
||||
id: testTelemetryObject.identifier.key
|
||||
});
|
||||
expect(conditionObj.result).toBeTrue();
|
||||
|
||||
conditionObj.getResult({
|
||||
value: '1',
|
||||
utc: 'Hi',
|
||||
id: '1234'
|
||||
});
|
||||
expect(conditionObj.result).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
@ -23,14 +23,10 @@
|
||||
import EventEmitter from 'EventEmitter';
|
||||
|
||||
export default class StyleRuleManager extends EventEmitter {
|
||||
constructor(styleConfiguration, openmct, callback, suppressSubscriptionOnEdit) {
|
||||
constructor(styleConfiguration, openmct, callback) {
|
||||
super();
|
||||
this.openmct = openmct;
|
||||
this.callback = callback;
|
||||
if (suppressSubscriptionOnEdit) {
|
||||
this.openmct.editor.on('isEditing', this.toggleSubscription.bind(this));
|
||||
this.isEditing = this.openmct.editor.editing;
|
||||
}
|
||||
if (styleConfiguration) {
|
||||
this.initialize(styleConfiguration);
|
||||
if (styleConfiguration.conditionSetIdentifier) {
|
||||
@ -41,25 +37,9 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
toggleSubscription(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
if (this.isEditing) {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
if (this.conditionSetIdentifier) {
|
||||
this.applySelectedConditionStyle();
|
||||
}
|
||||
} else if (this.conditionSetIdentifier) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
}
|
||||
|
||||
initialize(styleConfiguration) {
|
||||
this.conditionSetIdentifier = styleConfiguration.conditionSetIdentifier;
|
||||
this.staticStyle = styleConfiguration.staticStyle;
|
||||
this.selectedConditionId = styleConfiguration.selectedConditionId;
|
||||
this.defaultConditionId = styleConfiguration.defaultConditionId;
|
||||
this.updateConditionStylesMap(styleConfiguration.styles || []);
|
||||
}
|
||||
|
||||
@ -74,7 +54,7 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
this.handleConditionSetResultUpdated(output[0]);
|
||||
}
|
||||
});
|
||||
this.stopProvidingTelemetry = this.openmct.telemetry.subscribe(conditionSetDomainObject, this.handleConditionSetResultUpdated.bind(this));
|
||||
this.stopProvidingTelemetry = this.openmct.telemetry.subscribe(conditionSetDomainObject, output => this.handleConditionSetResultUpdated(output));
|
||||
});
|
||||
}
|
||||
|
||||
@ -86,16 +66,12 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
let isNewConditionSet = !this.conditionSetIdentifier ||
|
||||
!this.openmct.objects.areIdsEqual(this.conditionSetIdentifier, styleConfiguration.conditionSetIdentifier);
|
||||
this.initialize(styleConfiguration);
|
||||
if (this.isEditing) {
|
||||
this.applySelectedConditionStyle();
|
||||
} else {
|
||||
//Only resubscribe if the conditionSet has changed.
|
||||
if (isNewConditionSet) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateConditionStylesMap(conditionStyles) {
|
||||
let conditionStyleMap = {};
|
||||
@ -127,16 +103,6 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
applySelectedConditionStyle() {
|
||||
const conditionId = this.selectedConditionId || this.defaultConditionId;
|
||||
if (!conditionId) {
|
||||
this.applyStaticStyle();
|
||||
} else if (this.conditionalStyleMap[conditionId]) {
|
||||
this.currentStyle = this.conditionalStyleMap[conditionId];
|
||||
this.updateDomainObjectStyle();
|
||||
}
|
||||
}
|
||||
|
||||
applyStaticStyle() {
|
||||
if (this.staticStyle) {
|
||||
this.currentStyle = this.staticStyle.style;
|
||||
|
@ -30,7 +30,6 @@
|
||||
>
|
||||
<div class="c-condition-h__drop-target"></div>
|
||||
<div v-if="isEditing"
|
||||
:class="{'is-current': condition.id === currentConditionId}"
|
||||
class="c-condition c-condition--edit"
|
||||
>
|
||||
<!-- Edit view -->
|
||||
@ -168,7 +167,6 @@
|
||||
</div>
|
||||
<div v-else
|
||||
class="c-condition c-condition--browse"
|
||||
:class="{'is-current': condition.id === currentConditionId}"
|
||||
>
|
||||
<!-- Browse view -->
|
||||
<div class="c-condition__header">
|
||||
@ -201,10 +199,6 @@ export default {
|
||||
ConditionDescription
|
||||
},
|
||||
props: {
|
||||
currentConditionId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
condition: {
|
||||
type: Object,
|
||||
required: true
|
||||
|
@ -58,7 +58,6 @@
|
||||
<Condition v-for="(condition, index) in conditionCollection"
|
||||
:key="condition.id"
|
||||
:condition="condition"
|
||||
:current-condition-id="currentConditionId"
|
||||
:condition-index="index"
|
||||
:telemetry="telemetryObjs"
|
||||
:is-editing="isEditing"
|
||||
@ -108,8 +107,7 @@ export default {
|
||||
moveIndex: undefined,
|
||||
isDragging: false,
|
||||
defaultOutput: undefined,
|
||||
dragCounter: 0,
|
||||
currentConditionId: ''
|
||||
dragCounter: 0
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@ -147,7 +145,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleConditionSetResultUpdated(data) {
|
||||
this.currentConditionId = data.conditionId;
|
||||
this.$emit('conditionSetResultUpdated', data)
|
||||
},
|
||||
observeForChanges() {
|
||||
@ -200,7 +197,7 @@ export default {
|
||||
this.$emit('telemetryUpdated', this.telemetryObjs);
|
||||
},
|
||||
removeTelemetryObject(identifier) {
|
||||
let index = this.telemetryObjs.findIndex(obj => {
|
||||
let index = _.findIndex(this.telemetryObjs, (obj) => {
|
||||
let objId = this.openmct.objects.makeKeyString(obj.identifier);
|
||||
let id = this.openmct.objects.makeKeyString(identifier);
|
||||
return objId === id;
|
||||
|
@ -190,7 +190,6 @@
|
||||
}
|
||||
|
||||
.c-condition {
|
||||
border: 1px solid transparent;
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
|
||||
@ -235,12 +234,6 @@
|
||||
&__summary {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
&.is-current {
|
||||
$c: $colorBodyFg;
|
||||
border-color: rgba($c, 0.2);
|
||||
background: rgba($c, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** CONDITION DEFINITION, EDITING */
|
||||
|
@ -79,8 +79,6 @@
|
||||
<div v-for="(conditionStyle, index) in conditionalStyles"
|
||||
:key="index"
|
||||
class="c-inspect-styles__condition"
|
||||
:class="{'is-current': conditionStyle.conditionId === selectedConditionId}"
|
||||
@click="applySelectedConditionStyle(conditionStyle.conditionId)"
|
||||
>
|
||||
<condition-error :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
@ -108,7 +106,6 @@ import ConditionError from "@/plugins/condition/components/ConditionError.vue";
|
||||
import Vue from 'vue';
|
||||
import PreviewAction from "@/ui/preview/PreviewAction.js";
|
||||
import {getApplicableStylesForItem} from "@/plugins/condition/utils/styleUtils";
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
export default {
|
||||
name: 'ConditionalStylesView',
|
||||
@ -129,8 +126,7 @@ export default {
|
||||
isEditing: this.openmct.editor.isEditing(),
|
||||
conditions: undefined,
|
||||
conditionsLoaded: false,
|
||||
navigateToPath: '',
|
||||
selectedConditionId: ''
|
||||
navigateToPath: ''
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
@ -195,9 +191,6 @@ export default {
|
||||
if (this.stopObservingItems) {
|
||||
this.stopObservingItems();
|
||||
}
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
},
|
||||
initialize(conditionSetDomainObject) {
|
||||
//If there are new conditions in the conditionSet we need to set those styles to default
|
||||
@ -207,13 +200,6 @@ export default {
|
||||
},
|
||||
setEditState(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
if (this.isEditing) {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
} else {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
addConditionSet() {
|
||||
let conditionSetDomainObject;
|
||||
@ -284,44 +270,33 @@ export default {
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
if (this.itemId) {
|
||||
domainObjectStyles[this.itemId].conditionSetIdentifier = undefined;
|
||||
domainObjectStyles[this.itemId].selectedConditionId = undefined;
|
||||
domainObjectStyles[this.itemId].defaultConditionId = undefined;
|
||||
delete domainObjectStyles[this.itemId].conditionSetIdentifier;
|
||||
domainObjectStyles[this.itemId].styles = undefined;
|
||||
delete domainObjectStyles[this.itemId].styles;
|
||||
if (isEmpty(domainObjectStyles[this.itemId])) {
|
||||
if (_.isEmpty(domainObjectStyles[this.itemId])) {
|
||||
delete domainObjectStyles[this.itemId];
|
||||
}
|
||||
} else {
|
||||
domainObjectStyles.conditionSetIdentifier = undefined;
|
||||
domainObjectStyles.selectedConditionId = undefined;
|
||||
domainObjectStyles.defaultConditionId = undefined;
|
||||
delete domainObjectStyles.conditionSetIdentifier;
|
||||
domainObjectStyles.styles = undefined;
|
||||
delete domainObjectStyles.styles;
|
||||
}
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
if (_.isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
|
||||
this.persist(domainObjectStyles);
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
},
|
||||
updateDomainObjectItemStyles(newItems) {
|
||||
//check that all items that have been styles still exist. Otherwise delete those styles
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
let itemsToRemove = [];
|
||||
let keys = Object.keys(domainObjectStyles);
|
||||
//TODO: Need an easier way to find which properties are itemIds
|
||||
keys.forEach((key) => {
|
||||
const keyIsItemId = (key !== 'styles') &&
|
||||
if ((key !== 'styles') &&
|
||||
(key !== 'staticStyle') &&
|
||||
(key !== 'defaultConditionId') &&
|
||||
(key !== 'selectedConditionId') &&
|
||||
(key !== 'conditionSetIdentifier');
|
||||
if (keyIsItemId) {
|
||||
(key !== 'conditionSetIdentifier')) {
|
||||
if (!(newItems.find(item => item.id === key))) {
|
||||
itemsToRemove.push(key);
|
||||
}
|
||||
@ -338,7 +313,7 @@ export default {
|
||||
delete domainObjectStyles[this.itemId];
|
||||
}
|
||||
});
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
if (_.isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
this.persist(domainObjectStyles);
|
||||
@ -349,9 +324,6 @@ export default {
|
||||
}
|
||||
let conditionalStyles = [];
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
|
||||
if (conditionConfiguration.isDefault) {
|
||||
this.selectedConditionId = conditionConfiguration.id;
|
||||
}
|
||||
this.conditions[conditionConfiguration.id] = conditionConfiguration;
|
||||
let foundStyle = this.findStyleByConditionId(conditionConfiguration.id);
|
||||
if (foundStyle) {
|
||||
@ -367,27 +339,7 @@ export default {
|
||||
//we're doing this so that we remove styles for any conditions that have been removed from the condition set
|
||||
this.conditionalStyles = conditionalStyles;
|
||||
this.conditionsLoaded = true;
|
||||
this.persist(this.getDomainObjectConditionalStyle(this.selectedConditionId));
|
||||
if (!this.isEditing) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
subscribeToConditionSet() {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
if (this.conditionSetDomainObject) {
|
||||
this.openmct.telemetry.request(this.conditionSetDomainObject)
|
||||
.then(output => {
|
||||
if (output && output.length) {
|
||||
this.handleConditionSetResultUpdated(output[0]);
|
||||
}
|
||||
});
|
||||
this.stopProvidingTelemetry = this.openmct.telemetry.subscribe(this.conditionSetDomainObject, this.handleConditionSetResultUpdated.bind(this));
|
||||
}
|
||||
},
|
||||
handleConditionSetResultUpdated(resultData) {
|
||||
this.selectedConditionId = resultData ? resultData.conditionId : '';
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
},
|
||||
initializeStaticStyle(objectStyles) {
|
||||
let staticStyle = objectStyles && objectStyles.staticStyle;
|
||||
@ -412,19 +364,14 @@ export default {
|
||||
let found = this.findStyleByConditionId(conditionStyle.conditionId);
|
||||
if (found) {
|
||||
found.style = conditionStyle.style;
|
||||
this.selectedConditionId = found.conditionId;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
}
|
||||
},
|
||||
getDomainObjectConditionalStyle(defaultConditionId) {
|
||||
getDomainObjectConditionalStyle() {
|
||||
let objectStyle = {
|
||||
styles: this.conditionalStyles,
|
||||
staticStyle: this.staticStyle,
|
||||
selectedConditionId: this.selectedConditionId
|
||||
staticStyle: this.staticStyle
|
||||
};
|
||||
if (defaultConditionId) {
|
||||
objectStyle.defaultConditionId = defaultConditionId;
|
||||
}
|
||||
if (this.conditionSetDomainObject) {
|
||||
objectStyle.conditionSetIdentifier = this.conditionSetDomainObject.identifier;
|
||||
}
|
||||
@ -446,10 +393,6 @@ export default {
|
||||
getCondition(id) {
|
||||
return this.conditions ? this.conditions[id] : {};
|
||||
},
|
||||
applySelectedConditionStyle(conditionId) {
|
||||
this.selectedConditionId = conditionId;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
},
|
||||
persist(style) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration.objectStyles', style);
|
||||
}
|
||||
|
@ -50,7 +50,6 @@
|
||||
import StyleEditor from "./StyleEditor.vue";
|
||||
import PreviewAction from "@/ui/preview/PreviewAction.js";
|
||||
import { getApplicableStylesForItem, getConsolidatedStyleValues, getConditionalStyleForItem } from "@/plugins/condition/utils/styleUtils";
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
export default {
|
||||
name: 'MultiSelectStylesView',
|
||||
@ -179,7 +178,7 @@ export default {
|
||||
domainObjectStyles[itemId] = undefined;
|
||||
delete domainObjectStyles[this.itemId];
|
||||
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
if (_.isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
this.persist(this.domainObject, domainObjectStyles);
|
||||
@ -240,7 +239,7 @@ export default {
|
||||
if (this.isStaticAndConditionalStyles) {
|
||||
this.removeConditionalStyles(domainObjectStyles, item.id);
|
||||
}
|
||||
if (isEmpty(itemStaticStyle)) {
|
||||
if (_.isEmpty(itemStaticStyle)) {
|
||||
itemStaticStyle = undefined;
|
||||
domainObjectStyles[item.id] = undefined;
|
||||
} else {
|
||||
|
@ -1,601 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2020, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div class="c-inspector__styles c-inspect-styles">
|
||||
<div v-if="isStaticAndConditionalStyles"
|
||||
class="c-inspect-styles__mixed-static-and-conditional u-alert u-alert--block u-alert--with-icon"
|
||||
>
|
||||
Your selection includes one or more items that use Conditional Styling. Applying a static style below will replace any Conditional Styling with the new choice.
|
||||
</div>
|
||||
<template v-if="!conditionSetDomainObject">
|
||||
<div class="c-inspect-styles__header">
|
||||
Object Style
|
||||
</div>
|
||||
<div class="c-inspect-styles__content">
|
||||
<div v-if="staticStyle"
|
||||
class="c-inspect-styles__style"
|
||||
>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="isEditing"
|
||||
:mixed-styles="mixedStyles"
|
||||
@persist="updateStaticStyle"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
id="addConditionSet"
|
||||
class="c-button c-button--major c-toggle-styling-button labeled"
|
||||
@click="addConditionSet"
|
||||
>
|
||||
<span class="c-cs-button__label">Use Conditional Styling...</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="c-inspect-styles__header">
|
||||
Conditional Object Styles
|
||||
</div>
|
||||
<div class="c-inspect-styles__content c-inspect-styles__condition-set">
|
||||
<a v-if="conditionSetDomainObject"
|
||||
class="c-object-label icon-conditional"
|
||||
:href="navigateToPath"
|
||||
@click="navigateOrPreview"
|
||||
>
|
||||
<span class="c-object-label__name">{{ conditionSetDomainObject.name }}</span>
|
||||
</a>
|
||||
<template v-if="isEditing">
|
||||
<button
|
||||
id="changeConditionSet"
|
||||
class="c-button labeled"
|
||||
@click="addConditionSet"
|
||||
>
|
||||
<span class="c-button__label">Change...</span>
|
||||
</button>
|
||||
|
||||
<button class="c-click-icon icon-x"
|
||||
title="Remove conditional styles"
|
||||
@click="removeConditionSet"
|
||||
></button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="conditionsLoaded"
|
||||
class="c-inspect-styles__conditions"
|
||||
>
|
||||
<div v-for="(conditionStyle, index) in conditionalStyles"
|
||||
:key="index"
|
||||
class="c-inspect-styles__condition"
|
||||
:class="{'is-current': conditionStyle.conditionId === selectedConditionId}"
|
||||
@click="applySelectedConditionStyle(conditionStyle.conditionId)"
|
||||
>
|
||||
<condition-error :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
/>
|
||||
<condition-description :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
/>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="conditionStyle"
|
||||
:is-editing="isEditing"
|
||||
@persist="updateConditionalStyle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import StyleEditor from "./StyleEditor.vue";
|
||||
import PreviewAction from "@/ui/preview/PreviewAction.js";
|
||||
import { getApplicableStylesForItem, getConsolidatedStyleValues, getConditionSetIdentifierForItem } from "@/plugins/condition/utils/styleUtils";
|
||||
import ConditionSetSelectorDialog from "@/plugins/condition/components/inspector/ConditionSetSelectorDialog.vue";
|
||||
import ConditionError from "@/plugins/condition/components/ConditionError.vue";
|
||||
import ConditionDescription from "@/plugins/condition/components/ConditionDescription.vue";
|
||||
import Vue from 'vue';
|
||||
|
||||
export default {
|
||||
name: 'StylesView',
|
||||
components: {
|
||||
StyleEditor,
|
||||
ConditionError,
|
||||
ConditionDescription
|
||||
},
|
||||
inject: [
|
||||
'openmct',
|
||||
'selection'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
staticStyle: undefined,
|
||||
isEditing: this.openmct.editor.isEditing(),
|
||||
mixedStyles: [],
|
||||
isStaticAndConditionalStyles: false,
|
||||
conditionalStyles: [],
|
||||
conditionSetDomainObject: undefined,
|
||||
conditions: undefined,
|
||||
conditionsLoaded: false,
|
||||
navigateToPath: '',
|
||||
selectedConditionId: ''
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.removeListeners();
|
||||
},
|
||||
mounted() {
|
||||
this.items = [];
|
||||
this.previewAction = new PreviewAction(this.openmct);
|
||||
this.isMultipleSelection = this.selection.length > 1;
|
||||
this.getObjectsAndItemsFromSelection();
|
||||
if (!this.isMultipleSelection) {
|
||||
let objectStyles = this.getObjectStyles();
|
||||
this.initializeStaticStyle(objectStyles);
|
||||
if (objectStyles && objectStyles.conditionSetIdentifier) {
|
||||
this.openmct.objects.get(objectStyles.conditionSetIdentifier).then(this.initialize);
|
||||
this.conditionalStyles = objectStyles.styles;
|
||||
}
|
||||
} else {
|
||||
this.initializeStaticStyle();
|
||||
}
|
||||
this.openmct.editor.on('isEditing', this.setEditState);
|
||||
},
|
||||
methods: {
|
||||
getObjectStyles() {
|
||||
let objectStyles;
|
||||
if (this.domainObjectsById) {
|
||||
const domainObject = Object.values(this.domainObjectsById)[0];
|
||||
if (domainObject.configuration && domainObject.configuration.objectStyles) {
|
||||
objectStyles = domainObject.configuration.objectStyles;
|
||||
}
|
||||
} else if (this.items.length) {
|
||||
const itemId = this.items[0].id;
|
||||
if (this.domainObject.configuration && this.domainObject.configuration.objectStyles && this.domainObject.configuration.objectStyles[itemId]) {
|
||||
objectStyles = this.domainObject.configuration.objectStyles[itemId];
|
||||
}
|
||||
} else if (this.domainObject.configuration && this.domainObject.configuration.objectStyles) {
|
||||
objectStyles = this.domainObject.configuration.objectStyles;
|
||||
}
|
||||
return objectStyles;
|
||||
},
|
||||
setEditState(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
if (this.isEditing) {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
} else {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
enableConditionSetNav() {
|
||||
this.openmct.objects.getOriginalPath(this.conditionSetDomainObject.identifier).then(
|
||||
(objectPath) => {
|
||||
this.objectPath = objectPath;
|
||||
this.navigateToPath = '#/browse/' + this.objectPath
|
||||
.map(o => o && this.openmct.objects.makeKeyString(o.identifier))
|
||||
.reverse()
|
||||
.join('/');
|
||||
}
|
||||
);
|
||||
},
|
||||
navigateOrPreview(event) {
|
||||
// If editing, display condition set in Preview overlay; otherwise nav to it while browsing
|
||||
if (this.openmct.editor.isEditing()) {
|
||||
event.preventDefault();
|
||||
this.previewAction.invoke(this.objectPath);
|
||||
}
|
||||
},
|
||||
isItemType(type, item) {
|
||||
return item && (item.type === type);
|
||||
},
|
||||
hasConditionalStyle(domainObject, layoutItem) {
|
||||
const id = layoutItem ? layoutItem.id : undefined;
|
||||
return getConditionSetIdentifierForItem(domainObject, id) !== undefined;
|
||||
},
|
||||
getObjectsAndItemsFromSelection() {
|
||||
let domainObject;
|
||||
let subObjects = [];
|
||||
let itemsWithConditionalStyles = 0;
|
||||
|
||||
//multiple selection
|
||||
let itemInitialStyles = [];
|
||||
let itemStyle;
|
||||
this.selection.forEach((selectionItem) => {
|
||||
const item = selectionItem[0].context.item;
|
||||
const layoutItem = selectionItem[0].context.layoutItem;
|
||||
const isChildItem = selectionItem.length > 1;
|
||||
if (!isChildItem) {
|
||||
domainObject = item;
|
||||
itemStyle = getApplicableStylesForItem(item);
|
||||
if (this.hasConditionalStyle(item)) {
|
||||
itemsWithConditionalStyles += 1;
|
||||
}
|
||||
} else {
|
||||
this.canHide = true;
|
||||
domainObject = selectionItem[1].context.item;
|
||||
if (item && !layoutItem || this.isItemType('subobject-view', layoutItem)) {
|
||||
subObjects.push(item);
|
||||
itemStyle = getApplicableStylesForItem(item);
|
||||
if (this.hasConditionalStyle(item)) {
|
||||
itemsWithConditionalStyles += 1;
|
||||
}
|
||||
} else {
|
||||
itemStyle = getApplicableStylesForItem(domainObject, layoutItem || item);
|
||||
this.items.push({
|
||||
id: layoutItem.id,
|
||||
applicableStyles: itemStyle
|
||||
});
|
||||
if (this.hasConditionalStyle(item, layoutItem)) {
|
||||
itemsWithConditionalStyles += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
itemInitialStyles.push(itemStyle);
|
||||
});
|
||||
this.isStaticAndConditionalStyles = this.isMultipleSelection && itemsWithConditionalStyles;
|
||||
const {styles, mixedStyles} = getConsolidatedStyleValues(itemInitialStyles);
|
||||
this.initialStyles = styles;
|
||||
this.mixedStyles = mixedStyles;
|
||||
|
||||
this.domainObject = domainObject;
|
||||
this.removeListeners();
|
||||
if (this.domainObject) {
|
||||
this.stopObserving = this.openmct.objects.observe(this.domainObject, '*', newDomainObject => this.domainObject = newDomainObject);
|
||||
this.stopObservingItems = this.openmct.objects.observe(this.domainObject, 'configuration.items', this.updateDomainObjectItemStyles);
|
||||
}
|
||||
|
||||
subObjects.forEach(this.registerListener);
|
||||
},
|
||||
updateDomainObjectItemStyles(newItems) {
|
||||
let keys = Object.keys(this.domainObject.configuration.objectStyles || {});
|
||||
keys.forEach((key) => {
|
||||
if (this.isKeyItemId(key)) {
|
||||
if (!(newItems.find(item => item.id === key))) {
|
||||
this.removeItemStyles(key);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
isKeyItemId(key) {
|
||||
return (key !== 'styles') &&
|
||||
(key !== 'staticStyle') &&
|
||||
(key !== 'defaultConditionId') &&
|
||||
(key !== 'selectedConditionId') &&
|
||||
(key !== 'conditionSetIdentifier');
|
||||
},
|
||||
registerListener(domainObject) {
|
||||
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
|
||||
if (!this.domainObjectsById) {
|
||||
this.domainObjectsById = {};
|
||||
}
|
||||
|
||||
if (!this.domainObjectsById[id]) {
|
||||
this.domainObjectsById[id] = domainObject;
|
||||
this.observeObject(domainObject, id);
|
||||
}
|
||||
},
|
||||
observeObject(domainObject, id) {
|
||||
let unobserveObject = this.openmct.objects.observe(domainObject, '*', (newObject) => {
|
||||
this.domainObjectsById[id] = JSON.parse(JSON.stringify(newObject));
|
||||
});
|
||||
this.unObserveObjects.push(unobserveObject);
|
||||
},
|
||||
removeListeners() {
|
||||
if (this.stopObserving) {
|
||||
this.stopObserving();
|
||||
}
|
||||
if (this.stopObservingItems) {
|
||||
this.stopObservingItems();
|
||||
}
|
||||
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
|
||||
if (this.unObserveObjects) {
|
||||
this.unObserveObjects.forEach((unObserveObject) => {
|
||||
unObserveObject();
|
||||
});
|
||||
}
|
||||
this.unObserveObjects = [];
|
||||
},
|
||||
subscribeToConditionSet() {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
if (this.conditionSetDomainObject) {
|
||||
this.openmct.telemetry.request(this.conditionSetDomainObject)
|
||||
.then(output => {
|
||||
if (output && output.length) {
|
||||
this.handleConditionSetResultUpdated(output[0]);
|
||||
}
|
||||
});
|
||||
this.stopProvidingTelemetry = this.openmct.telemetry.subscribe(this.conditionSetDomainObject, this.handleConditionSetResultUpdated.bind(this));
|
||||
}
|
||||
},
|
||||
handleConditionSetResultUpdated(resultData) {
|
||||
this.selectedConditionId = resultData ? resultData.conditionId : '';
|
||||
},
|
||||
initialize(conditionSetDomainObject) {
|
||||
//If there are new conditions in the conditionSet we need to set those styles to default
|
||||
this.conditionSetDomainObject = conditionSetDomainObject;
|
||||
this.enableConditionSetNav();
|
||||
this.initializeConditionalStyles();
|
||||
},
|
||||
initializeConditionalStyles() {
|
||||
if (!this.conditions) {
|
||||
this.conditions = {};
|
||||
}
|
||||
let conditionalStyles = [];
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
|
||||
if (conditionConfiguration.isDefault) {
|
||||
this.selectedConditionId = conditionConfiguration.id;
|
||||
}
|
||||
this.conditions[conditionConfiguration.id] = conditionConfiguration;
|
||||
let foundStyle = this.findStyleByConditionId(conditionConfiguration.id);
|
||||
if (foundStyle) {
|
||||
foundStyle.style = Object.assign((this.canHide ? { isStyleInvisible: '' } : {}), this.initialStyles, foundStyle.style);
|
||||
conditionalStyles.push(foundStyle);
|
||||
} else {
|
||||
conditionalStyles.splice(index, 0, {
|
||||
conditionId: conditionConfiguration.id,
|
||||
style: Object.assign((this.canHide ? { isStyleInvisible: '' } : {}), this.initialStyles)
|
||||
});
|
||||
}
|
||||
});
|
||||
//we're doing this so that we remove styles for any conditions that have been removed from the condition set
|
||||
this.conditionalStyles = conditionalStyles;
|
||||
this.conditionsLoaded = true;
|
||||
this.getAndPersistStyles(null, this.selectedConditionId);
|
||||
if (!this.isEditing) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
//TODO: Double check how this works for single styles
|
||||
initializeStaticStyle(objectStyles) {
|
||||
let staticStyle = objectStyles && objectStyles.staticStyle;
|
||||
if (staticStyle) {
|
||||
this.staticStyle = {
|
||||
style: Object.assign({}, this.initialStyles, staticStyle.style)
|
||||
};
|
||||
} else {
|
||||
this.staticStyle = {
|
||||
style: Object.assign({}, this.initialStyles)
|
||||
};
|
||||
}
|
||||
},
|
||||
removeItemStyles(itemId) {
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
if (itemId && domainObjectStyles[itemId]) {
|
||||
delete domainObjectStyles[itemId];
|
||||
|
||||
if (Object.keys(domainObjectStyles).length <= 0) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
this.persist(this.domainObject, domainObjectStyles);
|
||||
}
|
||||
},
|
||||
findStyleByConditionId(id) {
|
||||
return this.conditionalStyles.find(conditionalStyle => conditionalStyle.conditionId === id);
|
||||
},
|
||||
getCondition(id) {
|
||||
return this.conditions ? this.conditions[id] : {};
|
||||
},
|
||||
addConditionSet() {
|
||||
let conditionSetDomainObject;
|
||||
const handleItemSelection = (item) => {
|
||||
if (item) {
|
||||
conditionSetDomainObject = item;
|
||||
}
|
||||
};
|
||||
const dismissDialog = (overlay, initialize) => {
|
||||
overlay.dismiss();
|
||||
if (initialize && conditionSetDomainObject) {
|
||||
this.conditionSetDomainObject = conditionSetDomainObject;
|
||||
this.conditionalStyles = [];
|
||||
this.initializeConditionalStyles();
|
||||
}
|
||||
};
|
||||
let vm = new Vue({
|
||||
provide: {
|
||||
openmct: this.openmct
|
||||
},
|
||||
components: {ConditionSetSelectorDialog},
|
||||
data() {
|
||||
return {
|
||||
handleItemSelection
|
||||
}
|
||||
},
|
||||
template: '<condition-set-selector-dialog @conditionSetSelected="handleItemSelection"></condition-set-selector-dialog>'
|
||||
}).$mount();
|
||||
|
||||
let overlay = this.openmct.overlays.overlay({
|
||||
element: vm.$el,
|
||||
size: 'small',
|
||||
buttons: [
|
||||
{
|
||||
label: 'OK',
|
||||
emphasis: 'true',
|
||||
callback: () => dismissDialog(overlay, true)
|
||||
},
|
||||
{
|
||||
label: 'Cancel',
|
||||
callback: () => dismissDialog(overlay, false)
|
||||
}
|
||||
],
|
||||
onDestroy: () => vm.$destroy()
|
||||
});
|
||||
},
|
||||
removeConditionSet() {
|
||||
this.conditionSetDomainObject = undefined;
|
||||
this.conditionalStyles = [];
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
if (this.domainObjectsById) {
|
||||
const domainObjects = Object.values(this.domainObjectsById);
|
||||
domainObjects.forEach(domainObject => {
|
||||
let objectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
|
||||
this.removeConditionalStyles(objectStyles);
|
||||
if (Object.keys(objectStyles).length <= 0) {
|
||||
objectStyles = undefined;
|
||||
}
|
||||
this.persist(domainObject, objectStyles);
|
||||
});
|
||||
}
|
||||
if (this.items.length) {
|
||||
this.items.forEach((item) => {
|
||||
const itemId = item.id;
|
||||
this.removeConditionalStyles(domainObjectStyles, itemId);
|
||||
if (Object.keys(domainObjectStyles[itemId]).length <= 0) {
|
||||
delete domainObjectStyles[itemId];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.removeConditionalStyles(domainObjectStyles);
|
||||
}
|
||||
if (Object.keys(domainObjectStyles).length <= 0) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
this.persist(this.domainObject, domainObjectStyles);
|
||||
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
},
|
||||
removeConditionalStyles(domainObjectStyles, itemId) {
|
||||
if (itemId && domainObjectStyles[itemId]) {
|
||||
domainObjectStyles[itemId].conditionSetIdentifier = undefined;
|
||||
delete domainObjectStyles[itemId].conditionSetIdentifier;
|
||||
domainObjectStyles[itemId].selectedConditionId = undefined;
|
||||
domainObjectStyles[itemId].defaultConditionId = undefined;
|
||||
domainObjectStyles[itemId].styles = undefined;
|
||||
delete domainObjectStyles[itemId].styles;
|
||||
} else {
|
||||
domainObjectStyles.conditionSetIdentifier = undefined;
|
||||
delete domainObjectStyles.conditionSetIdentifier;
|
||||
domainObjectStyles.selectedConditionId = undefined;
|
||||
domainObjectStyles.defaultConditionId = undefined;
|
||||
domainObjectStyles.styles = undefined;
|
||||
delete domainObjectStyles.styles;
|
||||
}
|
||||
},
|
||||
updateStaticStyle(staticStyle, property) {
|
||||
//update the static style for each of the layoutItems as well as each sub object item
|
||||
this.staticStyle = staticStyle;
|
||||
this.removeConditionSet();
|
||||
this.getAndPersistStyles(property);
|
||||
},
|
||||
updateConditionalStyle(conditionStyle, property) {
|
||||
let foundStyle = this.findStyleByConditionId(conditionStyle.conditionId);
|
||||
if (foundStyle) {
|
||||
foundStyle.style = conditionStyle.style;
|
||||
this.selectedConditionId = foundStyle.conditionId;
|
||||
this.getAndPersistStyles(property);
|
||||
}
|
||||
},
|
||||
getAndPersistStyles(property, defaultConditionId) {
|
||||
this.persist(this.domainObject, this.getDomainObjectStyle(this.domainObject, property, this.items, defaultConditionId));
|
||||
if (this.domainObjectsById) {
|
||||
const domainObjects = Object.values(this.domainObjectsById);
|
||||
domainObjects.forEach(domainObject => {
|
||||
this.persist(domainObject, this.getDomainObjectStyle(domainObject, property, null, defaultConditionId));
|
||||
});
|
||||
}
|
||||
if (!this.items.length && !this.domainObjectsById) {
|
||||
this.persist(this.domainObject, this.getDomainObjectStyle(this.domainObject, property, null, defaultConditionId));
|
||||
}
|
||||
this.isStaticAndConditionalStyles = false;
|
||||
if (property) {
|
||||
let foundIndex = this.mixedStyles.indexOf(property);
|
||||
if (foundIndex > -1) {
|
||||
this.mixedStyles.splice(foundIndex, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
getDomainObjectStyle(domainObject, property, items, defaultConditionId) {
|
||||
let objectStyle = {
|
||||
styles: this.conditionalStyles,
|
||||
staticStyle: this.staticStyle,
|
||||
selectedConditionId: this.selectedConditionId
|
||||
};
|
||||
if (defaultConditionId) {
|
||||
objectStyle.defaultConditionId = defaultConditionId;
|
||||
}
|
||||
if (this.conditionSetDomainObject) {
|
||||
objectStyle.conditionSetIdentifier = this.conditionSetDomainObject.identifier;
|
||||
}
|
||||
let domainObjectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
|
||||
|
||||
if (items) {
|
||||
items.forEach(item => {
|
||||
let itemStaticStyle = {};
|
||||
let itemConditionalStyle = { styles: []};
|
||||
if (!this.conditionSetDomainObject) {
|
||||
if (domainObjectStyles[item.id] && domainObjectStyles[item.id].staticStyle) {
|
||||
itemStaticStyle = domainObjectStyles[item.id].staticStyle.style;
|
||||
}
|
||||
if (item.applicableStyles[property]) {
|
||||
itemStaticStyle[property] = this.staticStyle.style[property];
|
||||
}
|
||||
if (Object.keys(itemStaticStyle).length <= 0) {
|
||||
itemStaticStyle = undefined;
|
||||
}
|
||||
domainObjectStyles[item.id] = { staticStyle: { style: itemStaticStyle } };
|
||||
} else {
|
||||
objectStyle.styles.forEach((conditionalStyle, index) => {
|
||||
let style = {};
|
||||
Object.keys(item.applicableStyles).concat(['isStyleInvisible']).forEach(key => {
|
||||
style[key] = conditionalStyle.style[key];
|
||||
});
|
||||
itemConditionalStyle.styles.push({
|
||||
...conditionalStyle,
|
||||
style
|
||||
});
|
||||
});
|
||||
domainObjectStyles[item.id] = {
|
||||
...domainObjectStyles[item.id],
|
||||
...objectStyle,
|
||||
...itemConditionalStyle
|
||||
};
|
||||
}
|
||||
});
|
||||
} else {
|
||||
domainObjectStyles = {
|
||||
...domainObjectStyles,
|
||||
...objectStyle
|
||||
};
|
||||
}
|
||||
|
||||
return domainObjectStyles;
|
||||
},
|
||||
applySelectedConditionStyle(conditionId) {
|
||||
this.selectedConditionId = conditionId;
|
||||
this.getAndPersistStyles();
|
||||
},
|
||||
persist(domainObject, style) {
|
||||
this.openmct.objects.mutate(domainObject, 'configuration.objectStyles', style);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -60,31 +60,6 @@
|
||||
|
||||
&__condition {
|
||||
@include discreteItem();
|
||||
border: 1px solid transparent;
|
||||
pointer-events: none; // Prevent selecting when the object isn't being edited
|
||||
|
||||
&.is-current {
|
||||
$c: $colorBodyFg;
|
||||
border-color: rgba($c, 0.2);
|
||||
background: rgba($c, 0.2);
|
||||
}
|
||||
|
||||
.is-editing & {
|
||||
cursor: pointer;
|
||||
pointer-events: initial;
|
||||
transition: $transOut;
|
||||
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, 0.1);
|
||||
transition: $transIn;
|
||||
}
|
||||
|
||||
&.is-current {
|
||||
$c: $editUIColorBg;
|
||||
border-color: $c;
|
||||
background: rgba($c, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-style {
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
import TelemetryCriterion from './TelemetryCriterion';
|
||||
import { evaluateResults } from "../utils/evaluator";
|
||||
import { getLatestTimestamp } from '../utils/time';
|
||||
|
||||
export default class AllTelemetryCriterion extends TelemetryCriterion {
|
||||
|
||||
@ -48,21 +47,6 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
||||
|
||||
updateTelemetry(telemetryObjects) {
|
||||
this.telemetryObjects = { ...telemetryObjects };
|
||||
this.removeTelemetryDataCache();
|
||||
}
|
||||
|
||||
removeTelemetryDataCache() {
|
||||
const telemetryCacheIds = Object.keys(this.telemetryDataCache);
|
||||
Object.values(this.telemetryObjects).forEach(telemetryObject => {
|
||||
const id = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
const foundIndex = telemetryCacheIds.indexOf(id);
|
||||
if (foundIndex > -1) {
|
||||
telemetryCacheIds.splice(foundIndex, 1);
|
||||
}
|
||||
});
|
||||
telemetryCacheIds.forEach(id => {
|
||||
delete (this.telemetryDataCache[id]);
|
||||
});
|
||||
}
|
||||
|
||||
formatData(data, telemetryObjects) {
|
||||
@ -108,53 +92,40 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
||||
this.result = evaluateResults(Object.values(this.telemetryDataCache), this.telemetry);
|
||||
}
|
||||
|
||||
requestLAD(telemetryObjects) {
|
||||
const options = {
|
||||
requestLAD(options) {
|
||||
options = Object.assign({},
|
||||
options,
|
||||
{
|
||||
strategy: 'latest',
|
||||
size: 1
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
if (!this.isValid()) {
|
||||
return this.formatData({}, telemetryObjects);
|
||||
return this.formatData({}, options.telemetryObjects);
|
||||
}
|
||||
|
||||
let keys = Object.keys(Object.assign({}, telemetryObjects));
|
||||
let keys = Object.keys(Object.assign({}, options.telemetryObjects));
|
||||
const telemetryRequests = keys
|
||||
.map(key => this.openmct.telemetry.request(
|
||||
telemetryObjects[key],
|
||||
options.telemetryObjects[key],
|
||||
options
|
||||
));
|
||||
|
||||
let telemetryDataCache = {};
|
||||
return Promise.all(telemetryRequests)
|
||||
.then(telemetryRequestsResults => {
|
||||
let latestTimestamp;
|
||||
const timeSystems = this.openmct.time.getAllTimeSystems();
|
||||
const timeSystem = this.openmct.time.timeSystem();
|
||||
|
||||
let latestDatum;
|
||||
telemetryRequestsResults.forEach((results, index) => {
|
||||
const latestDatum = results.length ? results[results.length - 1] : {};
|
||||
const datumId = keys[index];
|
||||
const normalizedDatum = this.createNormalizedDatum(latestDatum, telemetryObjects[datumId]);
|
||||
|
||||
telemetryDataCache[datumId] = this.computeResult(normalizedDatum);
|
||||
|
||||
latestTimestamp = getLatestTimestamp(
|
||||
latestTimestamp,
|
||||
normalizedDatum,
|
||||
timeSystems,
|
||||
timeSystem
|
||||
);
|
||||
latestDatum = results.length ? results[results.length - 1] : {};
|
||||
if (index < telemetryRequestsResults.length-1) {
|
||||
if (latestDatum) {
|
||||
this.telemetryDataCache[latestDatum.id] = this.computeResult(latestDatum);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const datum = {
|
||||
result: evaluateResults(Object.values(telemetryDataCache), this.telemetry),
|
||||
...latestTimestamp
|
||||
};
|
||||
|
||||
return {
|
||||
id: this.id,
|
||||
data: datum
|
||||
data: this.formatData(latestDatum, options.telemetryObjects)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -61,21 +61,6 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
this.telemetryObject = telemetryObjects[this.telemetryObjectIdAsString];
|
||||
}
|
||||
|
||||
createNormalizedDatum(telemetryDatum, endpoint) {
|
||||
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
||||
const metadata = this.openmct.telemetry.getMetadata(endpoint).valueMetadatas;
|
||||
|
||||
const normalizedDatum = Object.values(metadata).reduce((datum, metadatum) => {
|
||||
const formatter = this.openmct.telemetry.getValueFormatter(metadatum);
|
||||
datum[metadatum.key] = formatter.parse(telemetryDatum[metadatum.source]);
|
||||
return datum;
|
||||
}, {});
|
||||
|
||||
normalizedDatum.id = id;
|
||||
|
||||
return normalizedDatum;
|
||||
}
|
||||
|
||||
formatData(data) {
|
||||
const datum = {
|
||||
result: this.computeResult(data)
|
||||
@ -94,11 +79,14 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
this.result = this.computeResult(validatedData);
|
||||
}
|
||||
|
||||
requestLAD() {
|
||||
const options = {
|
||||
requestLAD(options) {
|
||||
options = Object.assign({},
|
||||
options,
|
||||
{
|
||||
strategy: 'latest',
|
||||
size: 1
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
if (!this.isValid()) {
|
||||
return {
|
||||
@ -112,11 +100,9 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
options
|
||||
).then(results => {
|
||||
const latestDatum = results.length ? results[results.length - 1] : {};
|
||||
const normalizedDatum = this.createNormalizedDatum(latestDatum, this.telemetryObject);
|
||||
|
||||
return {
|
||||
id: this.id,
|
||||
data: this.formatData(normalizedDatum)
|
||||
data: this.formatData(latestDatum)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -20,21 +20,25 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct } from "testUtils";
|
||||
import { createOpenMct } from "testTools";
|
||||
import ConditionPlugin from "./plugin";
|
||||
|
||||
let openmct = createOpenMct();
|
||||
openmct.install(new ConditionPlugin());
|
||||
|
||||
let conditionSetDefinition;
|
||||
let mockConditionSetDomainObject;
|
||||
let element;
|
||||
let child;
|
||||
|
||||
describe('the plugin', function () {
|
||||
let conditionSetDefinition;
|
||||
let mockConditionSetDomainObject;
|
||||
let element;
|
||||
let child;
|
||||
let openmct;
|
||||
|
||||
beforeAll((done) => {
|
||||
openmct = createOpenMct();
|
||||
openmct.install(new ConditionPlugin());
|
||||
|
||||
conditionSetDefinition = openmct.types.get('conditionSet').definition;
|
||||
const appHolder = document.createElement('div');
|
||||
appHolder.style.width = '640px';
|
||||
appHolder.style.height = '480px';
|
||||
|
||||
element = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
@ -51,7 +55,7 @@ describe('the plugin', function () {
|
||||
conditionSetDefinition.initialize(mockConditionSetDomainObject);
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
openmct.start(appHolder);
|
||||
});
|
||||
|
||||
let mockConditionSetObject = {
|
||||
|
@ -20,6 +20,8 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
const convertToNumbers = (input) => {
|
||||
let numberInputs = [];
|
||||
input.forEach(inputValue => numberInputs.push(Number(inputValue)));
|
||||
@ -32,10 +34,6 @@ const convertToStrings = (input) => {
|
||||
return stringInputs;
|
||||
};
|
||||
|
||||
const joinValues = (values, length) => {
|
||||
return values.slice(0, length).join(', ');
|
||||
};
|
||||
|
||||
export const OPERATIONS = [
|
||||
{
|
||||
name: 'equalTo',
|
||||
@ -46,7 +44,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is ' + joinValues(values, 1);
|
||||
return ' is ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -58,7 +56,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is not ' + joinValues(values, 1);
|
||||
return ' is not ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -70,7 +68,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' > ' + joinValues(values, 1);
|
||||
return ' > ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -82,7 +80,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' < ' + joinValues(values, 1);
|
||||
return ' < ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -94,7 +92,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' >= ' + joinValues(values, 1);
|
||||
return ' >= ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -106,7 +104,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' <= ' + joinValues(values, 1);
|
||||
return ' <= ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -148,7 +146,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' contains ' + joinValues(values, 1);
|
||||
return ' contains ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -160,7 +158,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' does not contain ' + joinValues(values, 1);
|
||||
return ' does not contain ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -172,7 +170,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' starts with ' + joinValues(values, 1);
|
||||
return ' starts with ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -184,7 +182,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' ends with ' + joinValues(values, 1);
|
||||
return ' ends with ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -196,7 +194,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is exactly ' + joinValues(values, 1);
|
||||
return ' is exactly ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -233,7 +231,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['enum'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is ' + joinValues(values, 1);
|
||||
return ' is ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -246,7 +244,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['enum'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is not ' + joinValues(values, 1);
|
||||
return ' is not ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -255,7 +253,7 @@ export const OPERATIONS = [
|
||||
const lhsValue = input[0] !== undefined ? input[0].toString() : '';
|
||||
if (input[1]) {
|
||||
const values = input[1].split(',');
|
||||
return values.find((value) => lhsValue === value.toString().trim());
|
||||
return values.find((value) => lhsValue === _.trim(value.toString()));
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@ -272,7 +270,7 @@ export const OPERATIONS = [
|
||||
const lhsValue = input[0] !== undefined ? input[0].toString() : '';
|
||||
if (input[1]) {
|
||||
const values = input[1].split(',');
|
||||
const found = values.find((value) => lhsValue === value.toString().trim());
|
||||
const found = values.find((value) => lhsValue === _.trim(value.toString()));
|
||||
return !found;
|
||||
}
|
||||
return false;
|
||||
|
@ -19,8 +19,6 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
const NONE_VALUE = '__no_value';
|
||||
|
||||
const styleProps = {
|
||||
@ -124,25 +122,12 @@ export const getConditionalStyleForItem = (domainObject, id) => {
|
||||
if (domainObjectStyles[id] && domainObjectStyles[id].conditionSetIdentifier) {
|
||||
return domainObjectStyles[id].styles;
|
||||
}
|
||||
} else if (domainObjectStyles.conditionSetIdentifier) {
|
||||
} else if (domainObjectStyles.staticStyle) {
|
||||
return domainObjectStyles.styles;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getConditionSetIdentifierForItem = (domainObject, id) => {
|
||||
let domainObjectStyles = domainObject && domainObject.configuration && domainObject.configuration.objectStyles;
|
||||
if (domainObjectStyles) {
|
||||
if (id) {
|
||||
if (domainObjectStyles[id] && domainObjectStyles[id].conditionSetIdentifier) {
|
||||
return domainObjectStyles[id].conditionSetIdentifier;
|
||||
}
|
||||
} else if (domainObjectStyles.conditionSetIdentifier) {
|
||||
return domainObjectStyles.conditionSetIdentifier;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Returns either existing static styles or uses SVG defaults if available
|
||||
export const getApplicableStylesForItem = (domainObject, item) => {
|
||||
const type = item && item.type;
|
||||
@ -169,7 +154,7 @@ export const getApplicableStylesForItem = (domainObject, item) => {
|
||||
};
|
||||
|
||||
export const getStylesWithoutNoneValue = (style) => {
|
||||
if (isEmpty(style) || !style) {
|
||||
if (_.isEmpty(style) || !style) {
|
||||
return;
|
||||
}
|
||||
let styleObj = {};
|
||||
|
@ -68,6 +68,7 @@
|
||||
|
||||
<script>
|
||||
import uuid from 'uuid';
|
||||
|
||||
import SubobjectView from './SubobjectView.vue'
|
||||
import TelemetryView from './TelemetryView.vue'
|
||||
import BoxView from './BoxView.vue'
|
||||
@ -75,7 +76,6 @@ import TextView from './TextView.vue'
|
||||
import LineView from './LineView.vue'
|
||||
import ImageView from './ImageView.vue'
|
||||
import EditMarquee from './EditMarquee.vue'
|
||||
import _ from 'lodash'
|
||||
|
||||
const ITEM_TYPE_VIEW_MAP = {
|
||||
'subobject-view': SubobjectView,
|
||||
@ -512,7 +512,7 @@ export default {
|
||||
}
|
||||
},
|
||||
updateTelemetryFormat(item, format) {
|
||||
let index = this.layoutItems.findIndex(item);
|
||||
let index = _.findIndex(this.layoutItems, item);
|
||||
item.format = format;
|
||||
this.mutate(`configuration.items[${index}]`, item);
|
||||
}
|
||||
|
@ -40,7 +40,6 @@
|
||||
|
||||
<script>
|
||||
import LayoutDrag from './../LayoutDrag'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
|
@ -62,7 +62,6 @@
|
||||
<script>
|
||||
|
||||
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
|
||||
import _ from 'lodash';
|
||||
|
||||
const START_HANDLE_QUADRANTS = {
|
||||
1: 'c-frame-edit__handle--sw',
|
||||
|
@ -52,7 +52,7 @@ export default {
|
||||
},
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager(this.objectStyle, this.openmct, this.updateStyle.bind(this), true);
|
||||
this.styleRuleManager = new StyleRuleManager(this.objectStyle, this.openmct, this.updateStyle.bind(this));
|
||||
} else {
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
import Layout from './components/DisplayLayout.vue'
|
||||
import Vue from 'vue'
|
||||
import objectUtils from 'objectUtils'
|
||||
import objectUtils from '../../api/objects/object-utils.js'
|
||||
import DisplayLayoutType from './DisplayLayoutType.js'
|
||||
import DisplayLayoutToolbar from './DisplayLayoutToolbar.js'
|
||||
import AlphaNumericFormatViewProvider from './AlphanumericFormatViewProvider.js'
|
||||
|
@ -62,7 +62,6 @@
|
||||
<script>
|
||||
import FilterField from './FilterField.vue';
|
||||
import ToggleSwitch from '../../../ui/components/ToggleSwitch.vue';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
@ -103,7 +102,7 @@ export default {
|
||||
hasActiveFilters() {
|
||||
// Should be true when the user has entered any filter values.
|
||||
return Object.values(this.persistedFilters).some(comparator => {
|
||||
return (typeof(comparator) === 'object' && !isEmpty(comparator));
|
||||
return (typeof(comparator) === 'object' && !_.isEmpty(comparator));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -27,8 +27,7 @@
|
||||
|
||||
<script>
|
||||
import FilterObject from './FilterObject.vue';
|
||||
import GlobalFilters from './GlobalFilters.vue';
|
||||
import _ from 'lodash';
|
||||
import GlobalFilters from './GlobalFilters.vue'
|
||||
|
||||
const FILTER_VIEW_TITLE = 'Filters applied';
|
||||
const FILTER_VIEW_TITLE_MIXED = 'Mixed filters applied';
|
||||
|
@ -64,7 +64,6 @@
|
||||
<script>
|
||||
import compositionLoader from './composition-loader';
|
||||
import ListItem from './ListItem.vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
components: {ListItem},
|
||||
|
@ -66,6 +66,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
autoScroll: true,
|
||||
date: '',
|
||||
filters : {
|
||||
brightness: 100,
|
||||
contrast: 100
|
||||
@ -77,39 +78,22 @@ export default {
|
||||
imageHistory: [],
|
||||
imageUrl: '',
|
||||
isPaused: false,
|
||||
metadata: {},
|
||||
requestCount: 0,
|
||||
timeFormat: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// set
|
||||
this.keystring = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
||||
this.imageFormat = this.openmct.telemetry.getValueFormatter(this.metadata.valuesForHints(['image'])[0]);
|
||||
// initialize
|
||||
this.timeKey = this.openmct.time.timeSystem().key;
|
||||
this.timeFormat = this.openmct.telemetry.getValueFormatter(this.metadata.value(this.timeKey));
|
||||
// listen
|
||||
this.openmct.time.on('bounds', this.boundsChange);
|
||||
this.openmct.time.on('timeSystem', this.timeSystemChange);
|
||||
// kickoff
|
||||
this.subscribe();
|
||||
this.requestHistory();
|
||||
this.subscribe(this.domainObject);
|
||||
},
|
||||
updated() {
|
||||
this.scrollToRight();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.unsubscribe) {
|
||||
this.unsubscribe();
|
||||
delete this.unsubscribe;
|
||||
}
|
||||
this.openmct.time.off('bounds', this.boundsChange);
|
||||
this.openmct.time.off('timeSystem', this.timeSystemChange);
|
||||
this.stopListening();
|
||||
},
|
||||
methods: {
|
||||
datumIsNotValid(datum) {
|
||||
datumMatchesMostRecent(datum) {
|
||||
if (this.imageHistory.length === 0) {
|
||||
return false;
|
||||
}
|
||||
@ -119,14 +103,7 @@ export default {
|
||||
const lastHistoryTime = this.timeFormat.format(this.imageHistory.slice(-1)[0]);
|
||||
const lastHistoryURL = this.imageFormat.format(this.imageHistory.slice(-1)[0]);
|
||||
|
||||
// datum is not valid if it matches the last datum in history,
|
||||
// or it is before the last datum in the history
|
||||
const datumTimeCheck = this.timeFormat.parse(datum);
|
||||
const historyTimeCheck = this.timeFormat.parse(this.imageHistory.slice(-1)[0]);
|
||||
const matchesLast = (datumTime === lastHistoryTime) && (datumURL === lastHistoryURL);
|
||||
const isStale = datumTimeCheck < historyTimeCheck;
|
||||
|
||||
return matchesLast || isStale;
|
||||
return (datumTime === lastHistoryTime) && (datumURL === lastHistoryURL);
|
||||
},
|
||||
getImageUrl(datum) {
|
||||
return datum ?
|
||||
@ -170,6 +147,21 @@ export default {
|
||||
|
||||
return this.isPaused;
|
||||
},
|
||||
requestHistory(bounds) {
|
||||
this.requestCount++;
|
||||
this.imageHistory = [];
|
||||
const requestId = this.requestCount;
|
||||
this.openmct.telemetry
|
||||
.request(this.domainObject, bounds)
|
||||
.then((values = []) => {
|
||||
if (this.requestCount > requestId) {
|
||||
return Promise.resolve('Stale request');
|
||||
}
|
||||
|
||||
values.forEach(this.updateHistory);
|
||||
this.updateValues(values[values.length - 1]);
|
||||
});
|
||||
},
|
||||
scrollToRight() {
|
||||
if (this.isPaused || !this.$refs.thumbsWrapper || !this.autoScroll) {
|
||||
return;
|
||||
@ -196,56 +188,40 @@ export default {
|
||||
image.selected = true;
|
||||
}
|
||||
},
|
||||
boundsChange(bounds, isTick) {
|
||||
if(!isTick) {
|
||||
this.requestHistory();
|
||||
stopListening() {
|
||||
if (this.unsubscribe) {
|
||||
this.unsubscribe();
|
||||
delete this.unsubscribe;
|
||||
}
|
||||
},
|
||||
requestHistory() {
|
||||
let bounds = this.openmct.time.bounds();
|
||||
this.requestCount++;
|
||||
const requestId = this.requestCount;
|
||||
this.imageHistory = [];
|
||||
this.openmct.telemetry
|
||||
.request(this.domainObject, bounds)
|
||||
.then((values = []) => {
|
||||
if (this.requestCount === requestId) {
|
||||
values.forEach(this.updateHistory, false);
|
||||
this.updateValues(values[values.length - 1]);
|
||||
}
|
||||
});
|
||||
},
|
||||
timeSystemChange(system) {
|
||||
// reset timesystem dependent variables
|
||||
this.timeKey = system.key;
|
||||
this.timeFormat = this.openmct.telemetry.getValueFormatter(this.metadata.value(this.timeKey));
|
||||
},
|
||||
subscribe() {
|
||||
subscribe(domainObject) {
|
||||
this.date = ''
|
||||
this.imageUrl = '';
|
||||
this.openmct.objects.get(this.keystring)
|
||||
.then((object) => {
|
||||
const metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
||||
this.timeKey = this.openmct.time.timeSystem().key;
|
||||
this.timeFormat = this.openmct.telemetry.getValueFormatter(metadata.value(this.timeKey));
|
||||
this.imageFormat = this.openmct.telemetry.getValueFormatter(metadata.valuesForHints(['image'])[0]);
|
||||
this.unsubscribe = this.openmct.telemetry
|
||||
.subscribe(this.domainObject, (datum) => {
|
||||
let parsedTimestamp = this.timeFormat.parse(datum[this.timeKey]),
|
||||
bounds = this.openmct.time.bounds();
|
||||
|
||||
if(parsedTimestamp >= bounds.start && parsedTimestamp <= bounds.end) {
|
||||
this.updateHistory(datum);
|
||||
this.updateValues(datum);
|
||||
}
|
||||
});
|
||||
|
||||
this.requestHistory(this.openmct.time.bounds());
|
||||
});
|
||||
},
|
||||
unselectAllImages() {
|
||||
this.imageHistory.forEach(image => image.selected = false);
|
||||
},
|
||||
updateHistory(datum, updateValues = true) {
|
||||
if (this.datumIsNotValid(datum)) {
|
||||
updateHistory(datum) {
|
||||
if (this.datumMatchesMostRecent(datum)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = _.sortedIndexBy(this.imageHistory, datum, this.timeFormat.format.bind(this.timeFormat));
|
||||
const index = _.sortedIndex(this.imageHistory, datum, this.timeFormat.format.bind(this.timeFormat));
|
||||
this.imageHistory.splice(index, 0, datum);
|
||||
|
||||
if(updateValues) {
|
||||
this.updateValues(datum);
|
||||
}
|
||||
},
|
||||
updateValues(datum) {
|
||||
if (this.isPaused) {
|
||||
|
@ -162,35 +162,20 @@ export default {
|
||||
}).show(this.embed.snapshot.src);
|
||||
},
|
||||
changeLocation() {
|
||||
this.openmct.time.stopClock();
|
||||
this.openmct.time.bounds({
|
||||
start: this.embed.bounds.start,
|
||||
end: this.embed.bounds.end
|
||||
});
|
||||
|
||||
const link = this.embed.historicLink;
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bounds = this.openmct.time.bounds();
|
||||
const isTimeBoundChanged = this.embed.bounds.start !== bounds.start
|
||||
|| this.embed.bounds.end !== bounds.end;
|
||||
const isFixedTimespanMode = !this.openmct.time.clock();
|
||||
|
||||
this.openmct.time.stopClock();
|
||||
let message = '';
|
||||
if (isTimeBoundChanged) {
|
||||
this.openmct.time.bounds({
|
||||
start: this.embed.bounds.start,
|
||||
end: this.embed.bounds.end
|
||||
});
|
||||
message = 'Time bound values changed';
|
||||
}
|
||||
|
||||
if (!isFixedTimespanMode) {
|
||||
message = 'Time bound values changed to fixed timespan mode';
|
||||
}
|
||||
|
||||
if (message.length) {
|
||||
this.openmct.notifications.alert(message);
|
||||
}
|
||||
|
||||
window.location.href = link;
|
||||
const message = 'Time bounds changed to fixed timespan mode';
|
||||
this.openmct.notifications.alert(message);
|
||||
},
|
||||
formatTime(unixTime, timeFormat) {
|
||||
return Moment.utc(unixTime).format(timeFormat);
|
||||
|
@ -221,7 +221,7 @@ export default {
|
||||
return position;
|
||||
},
|
||||
formatTime(unixTime, timeFormat) {
|
||||
return Moment.utc(unixTime).format(timeFormat);
|
||||
return Moment(unixTime).format(timeFormat);
|
||||
},
|
||||
moveSnapshot(snapshotId) {
|
||||
const snapshot = this.snapshotContainer.getSnapshot(snapshotId);
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
<script>
|
||||
import Snapshot from '../snapshot';
|
||||
import { getDefaultNotebook } from '../utils/notebook-storage';
|
||||
import { clearDefaultNotebook, getDefaultNotebook } from '../utils/notebook-storage';
|
||||
import { NOTEBOOK_DEFAULT, NOTEBOOK_SNAPSHOT } from '../notebook-constants';
|
||||
|
||||
export default {
|
||||
@ -40,18 +40,6 @@ export default {
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
ignoreLink: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
objectPath: {
|
||||
type: Array,
|
||||
default() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -72,21 +60,27 @@ export default {
|
||||
methods: {
|
||||
async setNotebookTypes() {
|
||||
const notebookTypes = [];
|
||||
let defaultPath = '';
|
||||
const defaultNotebook = getDefaultNotebook();
|
||||
|
||||
if (defaultNotebook) {
|
||||
const domainObject = defaultNotebook.domainObject;
|
||||
const domainObject = await this.openmct.objects.get(defaultNotebook.notebookMeta.identifier)
|
||||
.then(d => d);
|
||||
|
||||
if (domainObject.location) {
|
||||
const defaultPath = `${domainObject.name} - ${defaultNotebook.section.name} - ${defaultNotebook.page.name}`;
|
||||
if (!domainObject.location) {
|
||||
clearDefaultNotebook();
|
||||
} else {
|
||||
defaultPath = `${domainObject.name} - ${defaultNotebook.section.name} - ${defaultNotebook.page.name}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultPath.length !== 0) {
|
||||
notebookTypes.push({
|
||||
cssClass: 'icon-notebook',
|
||||
name: `Save to Notebook ${defaultPath}`,
|
||||
type: NOTEBOOK_DEFAULT
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
notebookTypes.push({
|
||||
cssClass: 'icon-notebook',
|
||||
@ -103,27 +97,17 @@ export default {
|
||||
this.showMenu = false;
|
||||
},
|
||||
snapshot(notebook) {
|
||||
this.hideMenu();
|
||||
|
||||
this.$nextTick(() => {
|
||||
const element = document.querySelector('.c-overlay__contents')
|
||||
|| document.getElementsByClassName('l-shell__main-container')[0];
|
||||
|
||||
let element = document.getElementsByClassName("l-shell__main-container")[0];
|
||||
const bounds = this.openmct.time.bounds();
|
||||
const link = !this.ignoreLink
|
||||
? window.location.href
|
||||
: null;
|
||||
|
||||
const objectPath = this.objectPath || this.openmct.router.path;
|
||||
const objectPath = this.openmct.router.path;
|
||||
const snapshotMeta = {
|
||||
bounds,
|
||||
link,
|
||||
link: window.location.href,
|
||||
objectPath,
|
||||
openmct: this.openmct
|
||||
};
|
||||
|
||||
this.notebookSnapshot.capture(snapshotMeta, notebook.type, element);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +239,6 @@ export default {
|
||||
const section = this.getSelectedSection();
|
||||
|
||||
return {
|
||||
domainObject: this.internalDomainObject,
|
||||
notebookMeta,
|
||||
section,
|
||||
page
|
||||
@ -441,7 +440,7 @@ export default {
|
||||
async updateDefaultNotebook(notebookStorage) {
|
||||
const defaultNotebookObject = await this.getDefaultNotebookObject();
|
||||
this.removeDefaultClass(defaultNotebookObject);
|
||||
setDefaultNotebook(this.openmct, notebookStorage);
|
||||
setDefaultNotebook(notebookStorage);
|
||||
this.addDefaultClass();
|
||||
this.defaultSectionId = notebookStorage.section.id;
|
||||
this.defaultPageId = notebookStorage.page.id;
|
||||
@ -496,7 +495,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (id !== defaultNotebookSection.id) {
|
||||
if (section.id !== defaultNotebookSection.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,46 +1,6 @@
|
||||
const NOTEBOOK_LOCAL_STORAGE = 'notebook-storage';
|
||||
let currentNotebookObject = null;
|
||||
let unlisten = null;
|
||||
|
||||
function defaultNotebookObjectChanged(newDomainObject) {
|
||||
if (newDomainObject.location !== null) {
|
||||
currentNotebookObject = newDomainObject;
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
notebookStorage.domainObject = newDomainObject;
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
unlisten = null;
|
||||
}
|
||||
|
||||
clearDefaultNotebook();
|
||||
}
|
||||
|
||||
function observeDefaultNotebookObject(openmct, notebookStorage) {
|
||||
const domainObject = notebookStorage.domainObject;
|
||||
if (currentNotebookObject
|
||||
&& currentNotebookObject.identifier.key === domainObject.identifier.key) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
unlisten = null;
|
||||
}
|
||||
|
||||
unlisten = openmct.objects.observe(notebookStorage.domainObject, '*', defaultNotebookObjectChanged);
|
||||
}
|
||||
|
||||
function saveDefaultNotebook(notebookStorage) {
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
}
|
||||
|
||||
export function clearDefaultNotebook() {
|
||||
currentNotebookObject = null;
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, null);
|
||||
}
|
||||
|
||||
@ -50,21 +10,20 @@ export function getDefaultNotebook() {
|
||||
return JSON.parse(notebookStorage);
|
||||
}
|
||||
|
||||
export function setDefaultNotebook(openmct, notebookStorage) {
|
||||
observeDefaultNotebookObject(openmct, notebookStorage);
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
export function setDefaultNotebook(notebookStorage) {
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
}
|
||||
|
||||
export function setDefaultNotebookSection(section) {
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
|
||||
notebookStorage.section = section;
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
|
||||
}
|
||||
|
||||
export function setDefaultNotebookPage(page) {
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
notebookStorage.page = page;
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
}
|
||||
|
@ -1,70 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="notifications.length > 0"
|
||||
class="c-indicator c-indicator--clickable icon-bell"
|
||||
:class="[severityClass]"
|
||||
>
|
||||
<span class="c-indicator__label">
|
||||
<button @click="toggleNotificationsList(true)">
|
||||
{{ notificationsCountMessage(notifications.length) }}
|
||||
</button>
|
||||
<button @click="dismissAllNotifications()">
|
||||
Clear All
|
||||
</button>
|
||||
</span>
|
||||
<span class="c-indicator__count">{{ notifications.length }}</span>
|
||||
|
||||
<notifications-list
|
||||
v-if="showNotificationsOverlay"
|
||||
:notifications="notifications"
|
||||
@close="toggleNotificationsList"
|
||||
@clear-all="dismissAllNotifications"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NotificationsList from './NotificationsList.vue';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
components: {
|
||||
NotificationsList
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
notifications: this.openmct.notifications.notifications,
|
||||
highest: this.openmct.notifications.highest,
|
||||
showNotificationsOverlay: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
severityClass() {
|
||||
return `s-status-${this.highest.severity}`;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.openmct.notifications.on('notification', this.updateNotifications);
|
||||
this.openmct.notifications.on('dismiss-all', this.updateNotifications);
|
||||
},
|
||||
methods: {
|
||||
dismissAllNotifications() {
|
||||
this.openmct.notifications.dismissAllNotifications();
|
||||
},
|
||||
toggleNotificationsList(flag) {
|
||||
this.showNotificationsOverlay = flag;
|
||||
},
|
||||
updateNotifications() {
|
||||
this.notifications = this.openmct.notifications.notifications;
|
||||
this.highest = this.openmct.notifications.highest;
|
||||
},
|
||||
notificationsCountMessage(count) {
|
||||
if (count > 1) {
|
||||
return `${count} Notifications`;
|
||||
} else {
|
||||
return `${count} Notification`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,85 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
class="c-message"
|
||||
:class="'message-severity-' + notification.model.severity"
|
||||
>
|
||||
<div class="c-ne__time-and-content">
|
||||
<div class="c-ne__time">
|
||||
<span>{{ notification.model.timestamp }}</span>
|
||||
</div>
|
||||
<div class="c-ne__content">
|
||||
<div class="w-message-contents">
|
||||
<div class="c-message__top-bar">
|
||||
<div class="c-message__title">{{ notification.model.message }}</div>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
<progress-bar
|
||||
v-if="isProgressNotification"
|
||||
:model="progressObject"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-overlay__button-bar">
|
||||
<button
|
||||
v-for="(dialogOption, index) in notification.model.options"
|
||||
:key="index"
|
||||
class="c-button"
|
||||
@click="dialogOption.callback()"
|
||||
>
|
||||
{{ dialogOption.label }}
|
||||
</button>
|
||||
<button
|
||||
v-if="notification.model.primaryOption"
|
||||
class="c-button c-button--major"
|
||||
@click="notification.model.primaryOption.callback()"
|
||||
>
|
||||
{{ notification.model.primaryOption.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProgressBar from '../../../ui/components/ProgressBar.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ProgressBar
|
||||
},
|
||||
props:{
|
||||
notification: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isProgressNotification: false,
|
||||
progressPerc: this.notification.model.progressPerc,
|
||||
progressText: this.notification.model.progressText
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
progressObject() {
|
||||
return {
|
||||
progressPerc: this.progressPerc,
|
||||
progressText: this.progressText
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.notification.model.progressPerc) {
|
||||
this.isProgressNotification = true;
|
||||
this.notification.on('progress', this.updateProgressBar)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateProgressBar(progressPerc, progressText) {
|
||||
this.progressPerc = progressPerc;
|
||||
this.progressText = progressText;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<div class="t-message-list c-overlay__contents">
|
||||
<div class="c-overlay__top-bar">
|
||||
<div class="c-overlay__dialog-title">Notifications</div>
|
||||
<div class="c-overlay__dialog-hint">
|
||||
{{ notificationsCountDisplayMessage(notifications.length) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-messages c-overlay__messages">
|
||||
<notification-message
|
||||
v-for="notification in notifications"
|
||||
:key="notification.model.timestamp"
|
||||
:notification="notification"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NotificationMessage from './NotificationMessage.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NotificationMessage
|
||||
},
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
notifications: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
mounted() {
|
||||
this.openOverlay();
|
||||
},
|
||||
methods: {
|
||||
openOverlay() {
|
||||
this.overlay = this.openmct.overlays.overlay({
|
||||
element: this.$el,
|
||||
size: 'large',
|
||||
dismissable: true,
|
||||
buttons: [
|
||||
{
|
||||
label: 'Clear All Notifications',
|
||||
emphasis: true,
|
||||
callback:() => {
|
||||
this.$emit('clear-all');
|
||||
this.overlay.dismiss();
|
||||
}
|
||||
}
|
||||
],
|
||||
onDestroy: () => {
|
||||
this.$emit('close', false);
|
||||
}
|
||||
});
|
||||
},
|
||||
notificationsCountDisplayMessage(count) {
|
||||
if (count > 1 || count === 0) {
|
||||
return `Displaying ${count} notifications`;
|
||||
} else {
|
||||
return `Displaying ${count} notification`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,71 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2020, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
import NotificationIndicatorPlugin from './plugin.js';
|
||||
import Vue from 'vue';
|
||||
import {
|
||||
createOpenMct
|
||||
} from 'testUtils';
|
||||
|
||||
describe('the plugin', () => {
|
||||
let notificationIndicatorPlugin,
|
||||
openmct,
|
||||
indicatorObject,
|
||||
indicatorElement,
|
||||
parentElement,
|
||||
mockMessages = ['error', 'test', 'notifications'];
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
|
||||
notificationIndicatorPlugin = new NotificationIndicatorPlugin();
|
||||
openmct.install(notificationIndicatorPlugin);
|
||||
|
||||
parentElement = document.createElement('div');
|
||||
|
||||
indicatorObject = openmct.indicators.indicatorObjects.find(indicator => indicator.key === 'notifications-indicator');
|
||||
indicatorElement = indicatorObject.element;
|
||||
|
||||
openmct.on('start', () => {
|
||||
mockMessages.forEach(message => {
|
||||
openmct.notifications.error(message);
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
describe('the indicator plugin element', () => {
|
||||
beforeEach(() => {
|
||||
parentElement.append(indicatorElement);
|
||||
return Vue.nextTick();
|
||||
});
|
||||
|
||||
it('notifies the user of the number of notifications', () => {
|
||||
let notificationCountElement = parentElement.querySelector('.c-indicator__count');
|
||||
|
||||
expect(notificationCountElement.innerText).toEqual(mockMessages.length.toString());
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -21,7 +21,7 @@
|
||||
-->
|
||||
<div ng-controller="StackedPlotController as stackedPlot"
|
||||
class="c-plot c-plot--stacked holder holder-plot has-control-bar">
|
||||
<div class="c-control-bar" ng-show="!stackedPlot.hideExportButtons">
|
||||
<div class="l-control-bar" ng-show="!stackedPlot.hideExportButtons">
|
||||
<span class="c-button-set c-button-set--strip-h">
|
||||
<button class="c-button icon-download"
|
||||
ng-click="stackedPlot.exportPNG()"
|
||||
|
@ -54,7 +54,6 @@ function (
|
||||
* @constructor
|
||||
*/
|
||||
function MCTChartController($scope) {
|
||||
this.$onInit = () => {
|
||||
this.$scope = $scope;
|
||||
this.isDestroyed = false;
|
||||
this.lines = [];
|
||||
@ -77,7 +76,6 @@ function (
|
||||
this.$scope.$watch('rectangles', this.scheduleDraw);
|
||||
this.config.series.forEach(this.onSeriesAdd, this);
|
||||
}
|
||||
}
|
||||
|
||||
eventHelpers.extend(MCTChartController.prototype);
|
||||
|
||||
@ -152,7 +150,7 @@ function (
|
||||
MCTChartController.prototype.destroy = function () {
|
||||
this.isDestroyed = true;
|
||||
this.stopListening();
|
||||
this.lines.forEach(line => line.destroy());
|
||||
_.invoke(this.lines, 'destroy');
|
||||
DrawLoader.releaseDrawAPI(this.drawAPI);
|
||||
};
|
||||
|
||||
|
@ -44,7 +44,7 @@ define([
|
||||
this.initialize(options);
|
||||
}
|
||||
|
||||
Object.assign(Collection.prototype, EventEmitter.prototype);
|
||||
_.extend(Collection.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(Collection.prototype);
|
||||
|
||||
Collection.extend = extend;
|
||||
@ -105,7 +105,12 @@ define([
|
||||
};
|
||||
|
||||
Collection.prototype.indexOf = function (model) {
|
||||
return this.models.findIndex(m => m === model);
|
||||
return _.findIndex(
|
||||
this.models,
|
||||
function (m) {
|
||||
return m === model;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
Collection.prototype.remove = function (model) {
|
||||
|
@ -49,7 +49,7 @@ define([
|
||||
this.initialize(options);
|
||||
}
|
||||
|
||||
Object.assign(Model.prototype, EventEmitter.prototype);
|
||||
_.extend(Model.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(Model.prototype);
|
||||
|
||||
Model.extend = extend;
|
||||
|
@ -146,7 +146,7 @@ define([
|
||||
strategy = 'minmax';
|
||||
}
|
||||
|
||||
options = Object.assign({}, { size: 1000, strategy, filters: this.filters }, options || {});
|
||||
options = _.extend({}, { size: 1000, strategy, filters: this.filters }, options || {});
|
||||
|
||||
if (!this.unsubscribe) {
|
||||
this.unsubscribe = this.openmct
|
||||
@ -160,7 +160,6 @@ define([
|
||||
);
|
||||
}
|
||||
|
||||
/* eslint-disable you-dont-need-lodash-underscore/concat */
|
||||
return this.openmct
|
||||
.telemetry
|
||||
.request(this.domainObject, options)
|
||||
@ -172,7 +171,6 @@ define([
|
||||
.value();
|
||||
this.reset(newPoints);
|
||||
}.bind(this));
|
||||
/* eslint-enable you-dont-need-lodash-underscore/concat */
|
||||
},
|
||||
/**
|
||||
* Update x formatter on x change.
|
||||
@ -272,7 +270,7 @@ define([
|
||||
* @private
|
||||
*/
|
||||
sortedIndex: function (point) {
|
||||
return _.sortedIndexBy(this.data, point, this.getXVal);
|
||||
return _.sortedIndex(this.data, point, this.getXVal);
|
||||
},
|
||||
/**
|
||||
* Update min/max stats for the series.
|
||||
@ -324,15 +322,7 @@ define([
|
||||
* a point to the end without dupe checking.
|
||||
*/
|
||||
add: function (point, appendOnly) {
|
||||
var insertIndex = this.data.length,
|
||||
currentYVal = this.getYVal(point),
|
||||
lastYVal = this.getYVal(this.data[insertIndex - 1]);
|
||||
|
||||
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
|
||||
console.warn('[Plot] Invalid Y Values detected');
|
||||
return;
|
||||
}
|
||||
|
||||
var insertIndex = this.data.length;
|
||||
if (!appendOnly) {
|
||||
insertIndex = this.sortedIndex(point);
|
||||
if (this.getXVal(this.data[insertIndex]) === this.getXVal(point)) {
|
||||
@ -342,21 +332,11 @@ define([
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.updateStats(point);
|
||||
point.mctLimitState = this.evaluate(point);
|
||||
this.data.splice(insertIndex, 0, point);
|
||||
this.emit('add', point, insertIndex, this);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
isValueInvalid: function (val) {
|
||||
return Number.isNaN(val) || val === undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a point from the data array and notify listeners.
|
||||
* @private
|
||||
|
@ -101,11 +101,11 @@ define([
|
||||
var plotObject = this.plot.get('domainObject');
|
||||
if (plotObject.type === 'telemetry.plot.overlay') {
|
||||
|
||||
var persistedIndex = plotObject.configuration.series.findIndex(s => {
|
||||
var persistedIndex = _.findIndex(plotObject.configuration.series, function (s) {
|
||||
return _.isEqual(identifier, s.identifier);
|
||||
});
|
||||
|
||||
var configIndex = this.models.findIndex(m => {
|
||||
var configIndex = _.findIndex(this.models, function (m) {
|
||||
return _.isEqual(m.domainObject.identifier, identifier);
|
||||
});
|
||||
|
||||
|
@ -182,23 +182,6 @@ define([
|
||||
this.set('format', yFormat.format.bind(yFormat));
|
||||
this.set('values', yMetadata.values);
|
||||
if (!label) {
|
||||
var labelName = series.map(function (s) {
|
||||
return s.metadata.value(s.get('yKey')).name;
|
||||
}).reduce(function (a, b) {
|
||||
if (a === undefined) {
|
||||
return b;
|
||||
}
|
||||
if (a === b) {
|
||||
return a;
|
||||
}
|
||||
return '';
|
||||
}, undefined);
|
||||
|
||||
if (labelName) {
|
||||
this.set('label', labelName);
|
||||
return;
|
||||
}
|
||||
|
||||
var labelUnits = series.map(function (s) {
|
||||
return s.metadata.value(s.get('yKey')).units;
|
||||
}).reduce(function (a, b) {
|
||||
@ -210,11 +193,22 @@ define([
|
||||
}
|
||||
return '';
|
||||
}, undefined);
|
||||
|
||||
if (labelUnits) {
|
||||
this.set('label', labelUnits);
|
||||
return;
|
||||
}
|
||||
var labelName = series.map(function (s) {
|
||||
return s.metadata.value(s.get('yKey')).name;
|
||||
}).reduce(function (a, b) {
|
||||
if (a === undefined) {
|
||||
return b;
|
||||
}
|
||||
if (a === b) {
|
||||
return a;
|
||||
}
|
||||
return '';
|
||||
}, undefined);
|
||||
this.set('label', labelName);
|
||||
}
|
||||
},
|
||||
defaults: function (options) {
|
||||
|
@ -51,7 +51,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Draw2D.prototype, EventEmitter.prototype);
|
||||
_.extend(Draw2D.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(Draw2D.prototype);
|
||||
|
||||
// Convert from logical to physical x coordinates
|
||||
|
@ -78,7 +78,7 @@ define([
|
||||
this.listenTo(this.canvas, "webglcontextlost", this.onContextLost, this);
|
||||
}
|
||||
|
||||
Object.assign(DrawWebGL.prototype, EventEmitter.prototype);
|
||||
_.extend(DrawWebGL.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(DrawWebGL.prototype);
|
||||
|
||||
DrawWebGL.prototype.onContextLost = function (event) {
|
||||
|
@ -23,7 +23,7 @@
|
||||
define([
|
||||
'../configuration/configStore',
|
||||
'../lib/eventHelpers',
|
||||
'objectUtils',
|
||||
'../../../../api/objects/object-utils',
|
||||
'lodash'
|
||||
], function (
|
||||
configStore,
|
||||
|
@ -31,7 +31,7 @@ define([
|
||||
function dynamicPathForKey(key) {
|
||||
return function (object, model) {
|
||||
var modelIdentifier = model.get('identifier');
|
||||
var index = object.configuration.series.findIndex(s => {
|
||||
var index = _.findIndex(object.configuration.series, function (s) {
|
||||
return _.isEqual(s.identifier, modelIdentifier);
|
||||
});
|
||||
return 'configuration.series[' + index + '].' + key;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user