mirror of
https://github.com/nasa/openmct.git
synced 2025-06-26 03:00:13 +00:00
Compare commits
5 Commits
troublesho
...
remove-unu
Author | SHA1 | Date | |
---|---|---|---|
e52ace77c3 | |||
6f3f43a555 | |||
08792d0113 | |||
59a4d05a0b | |||
f663a6a5b1 |
@ -2,7 +2,7 @@ version: 2.1
|
||||
executors:
|
||||
pw-focal-development:
|
||||
docker:
|
||||
- image: mcr.microsoft.com/playwright:v1.17.2-focal
|
||||
- image: mcr.microsoft.com/playwright:focal
|
||||
environment:
|
||||
NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed
|
||||
parameters:
|
||||
@ -76,14 +76,14 @@ jobs:
|
||||
node-version: <<parameters.node-version>>
|
||||
- run: npm audit --audit-level=low
|
||||
- generate_and_store_version_and_filesystem_artifacts
|
||||
node14-lint:
|
||||
parameters:
|
||||
node-version:
|
||||
type: string
|
||||
node10-lint:
|
||||
executor: pw-focal-development
|
||||
steps:
|
||||
- build_and_install:
|
||||
node-version: <<parameters.node-version>>
|
||||
- checkout
|
||||
- node/install:
|
||||
install-npm: false #Cannot install latest npm version with node10.
|
||||
node-version: lts/dubnium
|
||||
- run: npm install
|
||||
- run: npm run lint
|
||||
- generate_and_store_version_and_filesystem_artifacts
|
||||
unit-test:
|
||||
@ -141,8 +141,7 @@ jobs:
|
||||
workflows:
|
||||
overall-circleci-commit-status: #These jobs run on every commit
|
||||
jobs:
|
||||
- node14-lint:
|
||||
node-version: lts/fermium
|
||||
- node10-lint
|
||||
- unit-test:
|
||||
name: node12-chrome
|
||||
node-version: lts/erbium
|
||||
@ -159,6 +158,10 @@ workflows:
|
||||
suite: ci
|
||||
the-nightly: #These jobs do not run on PRs, but against master at night
|
||||
jobs:
|
||||
- unit-test:
|
||||
name: node10-chrome-nightly
|
||||
node-version: lts/dubnium
|
||||
browser: ChromeHeadless
|
||||
- unit-test:
|
||||
name: node12-firefoxESR-nightly
|
||||
node-version: lts/erbium
|
||||
|
@ -1 +0,0 @@
|
||||
## doc dump
|
@ -28,11 +28,9 @@ components. Tests are subject to code review along with the actual
|
||||
implementation, to ensure that tests are applicable and useful.
|
||||
|
||||
Unit tests should meet
|
||||
[test standards](CONTRIBUTING.md#test-standards)
|
||||
[test standards](https://github.com/nasa/openmctweb/blob/master/CONTRIBUTING.md#test-standards)
|
||||
as described in the contributing guide.
|
||||
|
||||
More about unit testing
|
||||
|
||||
### User Testing
|
||||
|
||||
User testing is performed at scheduled times involving target users
|
||||
@ -95,7 +93,7 @@ Before changes are merged, the author of the changes must perform:
|
||||
|
||||
Changes are not merged until the author has affirmed that both
|
||||
forms of testing have been performed successfully; this is documented
|
||||
by the [Author Checklist](CONTRIBUTING.md#author-checklist).
|
||||
by the [Author Checklist](https://github.com/nasa/openmctweb/blob/master/CONTRIBUTING.md#author-checklist).
|
||||
|
||||
### Per-sprint Testing
|
||||
|
||||
@ -137,7 +135,7 @@ For per-sprint testing, a testathon is typically performed at the beginning of t
|
||||
#### Process
|
||||
|
||||
1. Prior to the scheduled testathon, a list will be compiled of all issues that are closed and unverified.
|
||||
2. For each issue, testers should review the associated PR for testing instructions. See the contributing guide for instructions on [pull requests](CONTRIBUTING.md#merging).
|
||||
2. For each issue, testers should review the associated PR for testing instructions. See the contributing guide for instructions on [pull requests](https://github.com/nasa/openmct/blob/master/CONTRIBUTING.md#merging).
|
||||
3. As each issue is verified via testing, any team members testing it should leave a comment on that issue indicating that it has been verified fixed.
|
||||
4. If a bug is found that relates to an issue being tested, notes should be included on the associated issue, and the issue should be reopened. Bug notes should include reproduction steps.
|
||||
5. For any bugs that are not obviously related to any of the issues under test, a new issue should be created with details about the bug, including reproduction steps. If unsure about whether a bug relates to an issue being tested, just create a new issue.
|
||||
|
18
package.json
18
package.json
@ -4,16 +4,16 @@
|
||||
"description": "The Open MCT core platform",
|
||||
"devDependencies": {
|
||||
"@braintree/sanitize-url": "^5.0.2",
|
||||
"@percy/cli": "^1.0.0-beta.71",
|
||||
"@percy/cli": "^1.0.0-beta.70",
|
||||
"@percy/playwright": "^1.0.1",
|
||||
"@playwright/test": "^1.17.2",
|
||||
"@playwright/test": "^1.16.3",
|
||||
"allure-playwright": "^2.0.0-beta.14",
|
||||
"angular": ">=1.8.0",
|
||||
"angular-route": "1.4.14",
|
||||
"babel-eslint": "10.1.0",
|
||||
"comma-separated-values": "^3.6.4",
|
||||
"concurrently": "^3.6.1",
|
||||
"copy-webpack-plugin": "^10.2.0",
|
||||
"copy-webpack-plugin": "^9.0.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"css-loader": "^4.0.0",
|
||||
"d3-axis": "1.0.x",
|
||||
@ -36,7 +36,7 @@
|
||||
"istanbul-instrumenter-loader": "^3.0.1",
|
||||
"jasmine-core": "^4.0.0",
|
||||
"jsdoc": "^3.3.2",
|
||||
"karma": "6.3.10",
|
||||
"karma": "6.3.9",
|
||||
"karma-chrome-launcher": "3.1.0",
|
||||
"karma-cli": "2.0.0",
|
||||
"karma-coverage": "2.1.0",
|
||||
@ -45,20 +45,20 @@
|
||||
"karma-jasmine": "4.0.1",
|
||||
"karma-junit-reporter": "2.0.1",
|
||||
"karma-sourcemap-loader": "0.3.8",
|
||||
"karma-spec-reporter": "0.0.33",
|
||||
"karma-spec-reporter": "0.0.32",
|
||||
"karma-webpack": "^5.0.0",
|
||||
"location-bar": "^3.0.1",
|
||||
"lodash": "^4.17.12",
|
||||
"markdown-toc": "^0.11.7",
|
||||
"marked": "^0.3.5",
|
||||
"mini-css-extract-plugin": "2.4.5",
|
||||
"mini-css-extract-plugin": "^1.6.0",
|
||||
"minimist": "^1.2.5",
|
||||
"moment": "2.25.3",
|
||||
"moment-duration-format": "^2.2.2",
|
||||
"moment-timezone": "0.5.28",
|
||||
"node-bourbon": "^4.2.3",
|
||||
"painterro": "^1.2.56",
|
||||
"playwright": "^1.17.2",
|
||||
"playwright": "^1.16.3",
|
||||
"plotly.js-basic-dist": "^2.5.0",
|
||||
"plotly.js-gl2d-dist": "^2.5.0",
|
||||
"printj": "^1.2.1",
|
||||
@ -76,7 +76,7 @@
|
||||
"vue-eslint-parser": "8.0.1",
|
||||
"vue-loader": "15.9.8",
|
||||
"vue-template-compiler": "2.5.6",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack": "^5.53.0",
|
||||
"webpack-cli": "^4.0.0",
|
||||
"webpack-dev-middleware": "^3.1.3",
|
||||
"webpack-hot-middleware": "^2.22.3",
|
||||
@ -112,7 +112,7 @@
|
||||
"url": "https://github.com/nasa/openmct.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.1 <15.0.0"
|
||||
"node": ">=10.12.2 <16.0.0"
|
||||
},
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
|
@ -20,12 +20,18 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
// TODO delete me!
|
||||
class ImplementationLoader {
|
||||
load() {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
}
|
||||
|
||||
define([
|
||||
'./Constants',
|
||||
'./FrameworkInitializer',
|
||||
'./LogLevel',
|
||||
'./load/BundleLoader',
|
||||
'./resolve/ImplementationLoader',
|
||||
'./resolve/ExtensionResolver',
|
||||
'./resolve/BundleResolver',
|
||||
'./register/CustomRegistrars',
|
||||
@ -37,7 +43,6 @@ define([
|
||||
FrameworkInitializer,
|
||||
LogLevel,
|
||||
BundleLoader,
|
||||
ImplementationLoader,
|
||||
ExtensionResolver,
|
||||
BundleResolver,
|
||||
CustomRegistrars,
|
||||
@ -62,7 +67,7 @@ define([
|
||||
loader = new BundleLoader($http, $log, openmct.legacyRegistry),
|
||||
resolver = new BundleResolver(
|
||||
new ExtensionResolver(
|
||||
new ImplementationLoader({}),
|
||||
new ImplementationLoader(),
|
||||
$log
|
||||
),
|
||||
$log
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Module defining ImplementationLoader. Created by vwoeltje on 11/3/14.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Responsible for loading extension implementations
|
||||
* (AMD modules.) Acts as a wrapper around RequireJS to
|
||||
* provide a promise-like API.
|
||||
* @memberof platform/framework
|
||||
* @constructor
|
||||
* @param {*} require RequireJS, or an object with similar API
|
||||
* @param {*} $log Angular's logging service
|
||||
*/
|
||||
function ImplementationLoader(require) {
|
||||
this.require = require;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an extension's implementation; or, equivalently,
|
||||
* load an AMD module. This is fundamentally similar
|
||||
* to a call to RequireJS, except that the result is
|
||||
* wrapped in a promise. The promise will be fulfilled
|
||||
* with the loaded module, or rejected with the error
|
||||
* reported by Require.
|
||||
*
|
||||
* @param {string} path the path to the module to load
|
||||
* @returns {Promise} a promise for the specified module.
|
||||
*/
|
||||
ImplementationLoader.prototype.load = function loadModule(path) {
|
||||
var require = this.require;
|
||||
|
||||
return new Promise(function (fulfill, reject) {
|
||||
require([path], fulfill, reject);
|
||||
});
|
||||
};
|
||||
|
||||
return ImplementationLoader;
|
||||
}
|
||||
);
|
@ -1,88 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* ImplementationLoaderSpec. Created by vwoeltje on 11/6/14.
|
||||
*/
|
||||
define(
|
||||
["../../src/resolve/ImplementationLoader"],
|
||||
function (ImplementationLoader) {
|
||||
|
||||
describe("The implementation loader", function () {
|
||||
var required,
|
||||
loader;
|
||||
|
||||
function mockRequire(names, fulfill, reject) {
|
||||
required = {
|
||||
names: names,
|
||||
fulfill: fulfill,
|
||||
reject: reject
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
required = undefined;
|
||||
loader = new ImplementationLoader(mockRequire);
|
||||
});
|
||||
|
||||
it("passes script names to require", function () {
|
||||
loader.load("xyz.js");
|
||||
expect(required.names).toEqual(["xyz.js"]);
|
||||
});
|
||||
|
||||
it("wraps require results in a Promise that can resolve", function () {
|
||||
// Load and get the result
|
||||
var promise = loader.load("xyz.js").then(function (result) {
|
||||
expect(result).toEqual("test result");
|
||||
});
|
||||
|
||||
required.fulfill("test result");
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
it("wraps require results in a Promise that can reject", function () {
|
||||
var result,
|
||||
rejection;
|
||||
|
||||
// Load and get the result
|
||||
var promise = loader.load("xyz.js").then(
|
||||
function (v) {
|
||||
result = v;
|
||||
},
|
||||
function (v) {
|
||||
rejection = v;
|
||||
});
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
|
||||
required.reject("test result");
|
||||
|
||||
return promise.then(function () {
|
||||
expect(result).toBeUndefined();
|
||||
expect(rejection).toEqual("test result");
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,2 +0,0 @@
|
||||
return require('openmct');
|
||||
}));
|
@ -62,14 +62,12 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.refreshData = this.refreshData.bind(this);
|
||||
this.setTimeContext();
|
||||
|
||||
this.loadComposition();
|
||||
|
||||
this.openmct.time.on('bounds', this.refreshData);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.stopFollowingTimeContext();
|
||||
this.openmct.time.off('bounds', this.refreshData);
|
||||
|
||||
this.removeAllSubscriptions();
|
||||
|
||||
@ -81,21 +79,6 @@ export default {
|
||||
this.composition.off('remove', this.removeTelemetryObject);
|
||||
},
|
||||
methods: {
|
||||
setTimeContext() {
|
||||
this.stopFollowingTimeContext();
|
||||
|
||||
this.timeContext = this.openmct.time.getContextForView(this.path);
|
||||
this.followTimeContext();
|
||||
|
||||
},
|
||||
followTimeContext() {
|
||||
this.timeContext.on('bounds', this.refreshData);
|
||||
},
|
||||
stopFollowingTimeContext() {
|
||||
if (this.timeContext) {
|
||||
this.timeContext.off('bounds', this.refreshData);
|
||||
}
|
||||
},
|
||||
addTelemetryObject(telemetryObject) {
|
||||
// grab information we need from the added telmetry object
|
||||
const key = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
@ -164,7 +147,7 @@ export default {
|
||||
};
|
||||
},
|
||||
getOptions() {
|
||||
const { start, end } = this.timeContext.bounds();
|
||||
const { start, end } = this.openmct.time.bounds();
|
||||
|
||||
return {
|
||||
end,
|
||||
@ -264,10 +247,10 @@ export default {
|
||||
this.addTrace(trace, key);
|
||||
},
|
||||
isDataInTimeRange(datum, key) {
|
||||
const timeSystemKey = this.timeContext.timeSystem().key;
|
||||
const timeSystemKey = this.openmct.time.timeSystem().key;
|
||||
let currentTimestamp = this.parse(key, timeSystemKey, datum);
|
||||
|
||||
return currentTimestamp && this.timeContext.bounds().end >= currentTimestamp;
|
||||
return currentTimestamp && this.openmct.time.bounds().end >= currentTimestamp;
|
||||
},
|
||||
format(telemetryObjectKey, metadataKey, data) {
|
||||
const formats = this.telemetryObjectFormats[telemetryObjectKey];
|
||||
|
@ -48,7 +48,7 @@ define([
|
||||
|
||||
let indicator = {
|
||||
element: component.$mount().$el,
|
||||
key: 'global-clear-indicator',
|
||||
key: 'clear-data-indicator',
|
||||
priority: openmct.priority.DEFAULT
|
||||
};
|
||||
|
||||
|
@ -1,228 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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 ClearDataPlugin from './plugin.js';
|
||||
import Vue from 'vue';
|
||||
import { createOpenMct, resetApplicationState, createMouseEvent } from 'utils/testing';
|
||||
|
||||
describe('The Clear Data Plugin:', () => {
|
||||
let clearDataPlugin;
|
||||
|
||||
describe('The clear data action:', () => {
|
||||
let openmct;
|
||||
let selection;
|
||||
let mockObjectPath;
|
||||
let clearDataAction;
|
||||
let testViewObject;
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
|
||||
clearDataPlugin = new ClearDataPlugin(
|
||||
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
|
||||
{indicator: true}
|
||||
);
|
||||
openmct.install(clearDataPlugin);
|
||||
|
||||
clearDataAction = openmct.actions.getAction('clear-data-action');
|
||||
testViewObject = [{
|
||||
identifier: {
|
||||
key: "foo-table",
|
||||
namespace: ''
|
||||
},
|
||||
type: "table"
|
||||
}];
|
||||
openmct.router.path = testViewObject;
|
||||
mockObjectPath = [
|
||||
{
|
||||
name: 'Mock Table',
|
||||
type: 'table',
|
||||
identifier: {
|
||||
key: "foo-table",
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
];
|
||||
selection = [
|
||||
{
|
||||
context: {
|
||||
item: mockObjectPath[0]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
openmct.selection.select(selection);
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
openmct.router.path = null;
|
||||
|
||||
return resetApplicationState(openmct);
|
||||
});
|
||||
it('is installed', () => {
|
||||
expect(clearDataAction).toBeDefined();
|
||||
});
|
||||
|
||||
it('is applicable on applicable objects', () => {
|
||||
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
|
||||
expect(gatheredActions.applicableActions['clear-data-action']).toBeDefined();
|
||||
});
|
||||
|
||||
it('is not applicable on inapplicable objects', () => {
|
||||
testViewObject = [{
|
||||
identifier: {
|
||||
key: "foo-widget",
|
||||
namespace: ''
|
||||
},
|
||||
type: "widget"
|
||||
}];
|
||||
mockObjectPath = [
|
||||
{
|
||||
name: 'Mock Widget',
|
||||
type: 'widget',
|
||||
identifier: {
|
||||
key: "foo-widget",
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
];
|
||||
selection = [
|
||||
{
|
||||
context: {
|
||||
item: mockObjectPath[0]
|
||||
}
|
||||
}
|
||||
];
|
||||
openmct.selection.select(selection);
|
||||
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
|
||||
expect(gatheredActions.applicableActions['clear-data-action']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('is not applicable if object not in the selection path and not a layout', () => {
|
||||
selection = [
|
||||
{
|
||||
context: {
|
||||
item: {
|
||||
name: 'Some Random Widget',
|
||||
type: 'not-in-path-widget',
|
||||
identifier: {
|
||||
key: "something-else-widget",
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
openmct.selection.select(selection);
|
||||
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
|
||||
expect(gatheredActions.applicableActions['clear-data-action']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('is applicable if object not in the selection path and is a layout', () => {
|
||||
selection = [
|
||||
{
|
||||
context: {
|
||||
item: {
|
||||
name: 'Some Random Widget',
|
||||
type: 'not-in-path-widget',
|
||||
identifier: {
|
||||
key: "something-else-widget",
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
openmct.selection.select(selection);
|
||||
|
||||
testViewObject = [{
|
||||
identifier: {
|
||||
key: "foo-layout",
|
||||
namespace: ''
|
||||
},
|
||||
type: "layout"
|
||||
}];
|
||||
openmct.router.path = testViewObject;
|
||||
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
|
||||
expect(gatheredActions.applicableActions['clear-data-action']).toBeDefined();
|
||||
});
|
||||
|
||||
it('fires an event upon invocation', (done) => {
|
||||
openmct.objectViews.on('clearData', (domainObject) => {
|
||||
expect(domainObject).toEqual(testViewObject[0]);
|
||||
done();
|
||||
});
|
||||
clearDataAction.invoke(testViewObject);
|
||||
});
|
||||
});
|
||||
|
||||
describe('The clear data indicator:', () => {
|
||||
let openmct;
|
||||
let appHolder;
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
|
||||
clearDataPlugin = new ClearDataPlugin(
|
||||
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
|
||||
{indicator: true}
|
||||
);
|
||||
openmct.install(clearDataPlugin);
|
||||
appHolder = document.createElement('div');
|
||||
document.body.appendChild(appHolder);
|
||||
openmct.on('start', done);
|
||||
openmct.start(appHolder);
|
||||
});
|
||||
|
||||
it('installs', () => {
|
||||
const globalClearIndicator = openmct.indicators.indicatorObjects
|
||||
.find(indicator => indicator.key === 'global-clear-indicator').element;
|
||||
expect(globalClearIndicator).toBeDefined();
|
||||
});
|
||||
|
||||
it("renders its major elements", async () => {
|
||||
await Vue.nextTick();
|
||||
const indicatorClass = appHolder.querySelector('.c-indicator');
|
||||
const iconClass = appHolder.querySelector('.icon-clear-data');
|
||||
const indicatorLabel = appHolder.querySelector('.c-indicator__label');
|
||||
const buttonElement = indicatorLabel.querySelector('button');
|
||||
const hasMajorElements = Boolean(indicatorClass && iconClass && buttonElement);
|
||||
|
||||
expect(hasMajorElements).toBe(true);
|
||||
expect(buttonElement.innerText).toEqual('Clear Data');
|
||||
});
|
||||
|
||||
it("clicking the button fires the global clear", (done) => {
|
||||
const indicatorLabel = appHolder.querySelector('.c-indicator__label');
|
||||
const buttonElement = indicatorLabel.querySelector('button');
|
||||
const clickEvent = createMouseEvent('click');
|
||||
openmct.objectViews.on('clearData', () => {
|
||||
// when we click the button, this event should fire
|
||||
done();
|
||||
});
|
||||
buttonElement.dispatchEvent(clickEvent);
|
||||
});
|
||||
});
|
||||
});
|
143
src/plugins/clearData/test/ClearDataActionSpec.js
Normal file
143
src/plugins/clearData/test/ClearDataActionSpec.js
Normal file
@ -0,0 +1,143 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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 ClearDataActionPlugin from '../plugin.js';
|
||||
import ClearDataAction from '../ClearDataAction.js';
|
||||
|
||||
describe('When the Clear Data Plugin is installed,', () => {
|
||||
const mockObjectViews = jasmine.createSpyObj('objectViews', ['emit']);
|
||||
const mockIndicatorProvider = jasmine.createSpyObj('indicators', ['add']);
|
||||
const mockActionsProvider = jasmine.createSpyObj('actions', ['register']);
|
||||
const goodMockSelectionPath = [[{
|
||||
context: {
|
||||
item: {
|
||||
identifier: {
|
||||
key: 'apple',
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}]];
|
||||
|
||||
const openmct = {
|
||||
objectViews: mockObjectViews,
|
||||
indicators: mockIndicatorProvider,
|
||||
priority: {
|
||||
DEFAULT: 0
|
||||
},
|
||||
actions: mockActionsProvider,
|
||||
install: function (plugin) {
|
||||
plugin(this);
|
||||
},
|
||||
selection: {
|
||||
get: function () {
|
||||
return goodMockSelectionPath;
|
||||
}
|
||||
},
|
||||
objects: {
|
||||
areIdsEqual: function (obj1, obj2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mockObjectPath = [
|
||||
{
|
||||
name: 'mockObject1',
|
||||
type: 'apple'
|
||||
},
|
||||
{
|
||||
name: 'mockObject2',
|
||||
type: 'banana'
|
||||
}
|
||||
];
|
||||
|
||||
it('Global Clear Indicator is installed', () => {
|
||||
openmct.install(ClearDataActionPlugin(openmct, {indicator: true}));
|
||||
|
||||
expect(mockIndicatorProvider.add).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Clear Data context menu action is installed', () => {
|
||||
openmct.install(ClearDataActionPlugin(openmct, []));
|
||||
|
||||
expect(mockActionsProvider.register).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('clear data action emits a clearData event when invoked', () => {
|
||||
const action = new ClearDataAction(openmct);
|
||||
|
||||
action.invoke(mockObjectPath);
|
||||
|
||||
expect(mockObjectViews.emit).toHaveBeenCalledWith('clearData', mockObjectPath[0]);
|
||||
});
|
||||
|
||||
it('clears data on applicable objects', () => {
|
||||
let action = new ClearDataAction(openmct, ['apple']);
|
||||
|
||||
const actionApplies = action.appliesTo(mockObjectPath);
|
||||
|
||||
expect(actionApplies).toBe(true);
|
||||
});
|
||||
|
||||
it('does not clear data on inapplicable objects', () => {
|
||||
let action = new ClearDataAction(openmct, ['pineapple']);
|
||||
|
||||
const actionApplies = action.appliesTo(mockObjectPath);
|
||||
|
||||
expect(actionApplies).toBe(false);
|
||||
});
|
||||
|
||||
it('does not clear data if not in the selection path and not a layout', () => {
|
||||
openmct.objects = {
|
||||
areIdsEqual: function (obj1, obj2) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
openmct.router = {
|
||||
path: [{type: 'not-a-layout'}]
|
||||
};
|
||||
|
||||
let action = new ClearDataAction(openmct, ['apple']);
|
||||
|
||||
const actionApplies = action.appliesTo(mockObjectPath);
|
||||
|
||||
expect(actionApplies).toBe(false);
|
||||
});
|
||||
|
||||
it('does clear data if not in the selection path and is a layout', () => {
|
||||
openmct.objects = {
|
||||
areIdsEqual: function (obj1, obj2) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
openmct.router = {
|
||||
path: [{type: 'layout'}]
|
||||
};
|
||||
|
||||
let action = new ClearDataAction(openmct, ['apple']);
|
||||
|
||||
const actionApplies = action.appliesTo(mockObjectPath);
|
||||
|
||||
expect(actionApplies).toBe(true);
|
||||
});
|
||||
});
|
@ -109,7 +109,7 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
if (!styleConfiguration || !styleConfiguration.conditionSetIdentifier) {
|
||||
this.initialize(styleConfiguration || {});
|
||||
this.applyStaticStyle();
|
||||
this.destroy(true);
|
||||
this.destroy();
|
||||
} else {
|
||||
let isNewConditionSet = !this.conditionSetIdentifier
|
||||
|| !this.openmct.objects.areIdsEqual(this.conditionSetIdentifier, styleConfiguration.conditionSetIdentifier);
|
||||
@ -180,17 +180,15 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
this.updateDomainObjectStyle();
|
||||
}
|
||||
|
||||
destroy(skipEventListeners) {
|
||||
destroy() {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
|
||||
this.stopProvidingTelemetry();
|
||||
delete this.stopProvidingTelemetry;
|
||||
}
|
||||
|
||||
if (!skipEventListeners) {
|
||||
this.openmct.time.off("bounds", this.refreshData);
|
||||
this.openmct.editor.off('isEditing', this.toggleSubscription);
|
||||
}
|
||||
this.openmct.time.off("bounds", this.refreshData);
|
||||
this.openmct.editor.off('isEditing', this.toggleSubscription);
|
||||
|
||||
this.conditionSetIdentifier = undefined;
|
||||
}
|
||||
|
@ -0,0 +1,475 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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">
|
||||
<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"
|
||||
>
|
||||
<StyleEditor class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="isEditing"
|
||||
@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"
|
||||
@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)"
|
||||
/>
|
||||
<StyleEditor 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 SelectorDialogTree from '@/ui/components/SelectorDialogTree.vue';
|
||||
import ConditionDescription from "@/plugins/condition/components/ConditionDescription.vue";
|
||||
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',
|
||||
components: {
|
||||
ConditionDescription,
|
||||
ConditionError,
|
||||
StyleEditor
|
||||
},
|
||||
inject: [
|
||||
'openmct',
|
||||
'selection'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
conditionalStyles: [],
|
||||
staticStyle: undefined,
|
||||
conditionSetDomainObject: undefined,
|
||||
isEditing: this.openmct.editor.isEditing(),
|
||||
conditions: undefined,
|
||||
conditionsLoaded: false,
|
||||
navigateToPath: '',
|
||||
selectedConditionId: ''
|
||||
};
|
||||
},
|
||||
destroyed() {
|
||||
this.removeListeners();
|
||||
},
|
||||
mounted() {
|
||||
this.itemId = '';
|
||||
this.getDomainObjectFromSelection();
|
||||
this.previewAction = new PreviewAction(this.openmct);
|
||||
if (this.domainObject.configuration && this.domainObject.configuration.objectStyles) {
|
||||
let objectStyles = this.itemId ? this.domainObject.configuration.objectStyles[this.itemId] : this.domainObject.configuration.objectStyles;
|
||||
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: {
|
||||
isItemType(type, item) {
|
||||
return item && (item.type === type);
|
||||
},
|
||||
getDomainObjectFromSelection() {
|
||||
let layoutItem;
|
||||
let domainObject;
|
||||
|
||||
if (this.selection[0].length > 1) {
|
||||
//If there are more than 1 items in the this.selection[0] list, the first one could either be a sub domain object OR a layout drawing control.
|
||||
//The second item in the this.selection[0] list is the container object (usually a layout)
|
||||
layoutItem = this.selection[0][0].context.layoutItem;
|
||||
const item = this.selection[0][0].context.item;
|
||||
this.canHide = true;
|
||||
if (item
|
||||
&& (!layoutItem || (this.isItemType('subobject-view', layoutItem)))) {
|
||||
domainObject = item;
|
||||
} else {
|
||||
domainObject = this.selection[0][1].context.item;
|
||||
if (layoutItem) {
|
||||
this.itemId = layoutItem.id;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
domainObject = this.selection[0][0].context.item;
|
||||
}
|
||||
|
||||
this.domainObject = domainObject;
|
||||
this.initialStyles = getApplicableStylesForItem(domainObject, layoutItem);
|
||||
this.$nextTick(() => {
|
||||
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);
|
||||
}
|
||||
});
|
||||
},
|
||||
removeListeners() {
|
||||
if (this.stopObserving) {
|
||||
this.stopObserving();
|
||||
}
|
||||
|
||||
if (this.stopObservingItems) {
|
||||
this.stopObservingItems();
|
||||
}
|
||||
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
delete this.stopProvidingTelemetry;
|
||||
}
|
||||
},
|
||||
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();
|
||||
},
|
||||
setEditState(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
if (this.isEditing) {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
delete this.stopProvidingTelemetry;
|
||||
}
|
||||
} else {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
addConditionSet() {
|
||||
let conditionSetDomainObject;
|
||||
let self = this;
|
||||
|
||||
function handleItemSelection({ item }) {
|
||||
if (item) {
|
||||
conditionSetDomainObject = item;
|
||||
}
|
||||
}
|
||||
|
||||
function dismissDialog(overlay, initialize) {
|
||||
overlay.dismiss();
|
||||
if (initialize && conditionSetDomainObject) {
|
||||
self.conditionSetDomainObject = conditionSetDomainObject;
|
||||
self.conditionalStyles = [];
|
||||
self.initializeConditionalStyles();
|
||||
}
|
||||
}
|
||||
|
||||
let vm = new Vue({
|
||||
components: { SelectorDialogTree },
|
||||
provide: {
|
||||
openmct: this.openmct
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
handleItemSelection,
|
||||
title: 'Select Condition Set'
|
||||
};
|
||||
},
|
||||
template: '<selector-dialog-tree :title="title" @treeItemSelected="handleItemSelection"></selector-dialog-tree>'
|
||||
}).$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()
|
||||
});
|
||||
},
|
||||
enableConditionSetNav() {
|
||||
this.openmct.objects.getOriginalPath(this.conditionSetDomainObject.identifier).then(
|
||||
(objectPath) => {
|
||||
this.objectPath = objectPath;
|
||||
this.navigateToPath = '#/browse/' + this.openmct.objects.getRelativePath(this.objectPath);
|
||||
}
|
||||
);
|
||||
},
|
||||
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);
|
||||
} else {
|
||||
this.openmct.router.navigate(this.navigateToPath);
|
||||
}
|
||||
},
|
||||
removeConditionSet() {
|
||||
this.conditionSetDomainObject = undefined;
|
||||
this.conditionalStyles = [];
|
||||
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])) {
|
||||
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)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
|
||||
this.persist(domainObjectStyles);
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
delete 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')
|
||||
&& (key !== 'staticStyle')
|
||||
&& (key !== 'defaultConditionId')
|
||||
&& (key !== 'selectedConditionId')
|
||||
&& (key !== 'conditionSetIdentifier');
|
||||
if (keyIsItemId) {
|
||||
if (!(newItems.find(item => item.id === key))) {
|
||||
itemsToRemove.push(key);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (itemsToRemove.length) {
|
||||
this.removeItemStyles(itemsToRemove, domainObjectStyles);
|
||||
}
|
||||
},
|
||||
removeItemStyles(itemIds, domainObjectStyles) {
|
||||
itemIds.forEach(itemId => {
|
||||
if (domainObjectStyles[itemId]) {
|
||||
domainObjectStyles[itemId] = undefined;
|
||||
delete domainObjectStyles[this.itemId];
|
||||
}
|
||||
});
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
|
||||
this.persist(domainObjectStyles);
|
||||
},
|
||||
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.persist(this.getDomainObjectConditionalStyle(this.selectedConditionId));
|
||||
if (!this.isEditing) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
subscribeToConditionSet() {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
delete 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 : '';
|
||||
},
|
||||
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)
|
||||
};
|
||||
}
|
||||
},
|
||||
findStyleByConditionId(id) {
|
||||
return this.conditionalStyles.find(conditionalStyle => conditionalStyle.conditionId === id);
|
||||
},
|
||||
updateStaticStyle(staticStyle) {
|
||||
this.staticStyle = staticStyle;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
},
|
||||
updateConditionalStyle(conditionStyle) {
|
||||
let found = this.findStyleByConditionId(conditionStyle.conditionId);
|
||||
if (found) {
|
||||
found.style = conditionStyle.style;
|
||||
this.selectedConditionId = found.conditionId;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
}
|
||||
},
|
||||
getDomainObjectConditionalStyle(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 = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
|
||||
if (this.itemId) {
|
||||
domainObjectStyles[this.itemId] = objectStyle;
|
||||
} else {
|
||||
//we're deconstructing here to ensure that if an item within a domainObject already had a style we don't lose it
|
||||
domainObjectStyles = {
|
||||
...domainObjectStyles,
|
||||
...objectStyle
|
||||
};
|
||||
}
|
||||
|
||||
return domainObjectStyles;
|
||||
},
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -0,0 +1,280 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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 class="c-inspect-styles__header">
|
||||
Object Style
|
||||
</div>
|
||||
<div class="c-inspect-styles__content">
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
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',
|
||||
components: {
|
||||
StyleEditor
|
||||
},
|
||||
inject: [
|
||||
'openmct',
|
||||
'selection'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
staticStyle: undefined,
|
||||
isEditing: this.openmct.editor.isEditing(),
|
||||
mixedStyles: [],
|
||||
isStaticAndConditionalStyles: false
|
||||
};
|
||||
},
|
||||
destroyed() {
|
||||
this.removeListeners();
|
||||
},
|
||||
mounted() {
|
||||
this.items = [];
|
||||
this.previewAction = new PreviewAction(this.openmct);
|
||||
this.getObjectsAndItemsFromSelection();
|
||||
this.initializeStaticStyle();
|
||||
this.openmct.editor.on('isEditing', this.setEditState);
|
||||
},
|
||||
methods: {
|
||||
isItemType(type, item) {
|
||||
return item && (item.type === type);
|
||||
},
|
||||
hasConditionalStyles(domainObject, id) {
|
||||
return getConditionalStyleForItem(domainObject, id) !== undefined;
|
||||
},
|
||||
getObjectsAndItemsFromSelection() {
|
||||
let domainObject;
|
||||
let subObjects = [];
|
||||
|
||||
//multiple selection
|
||||
let itemInitialStyles = [];
|
||||
let itemStyle;
|
||||
this.selection.forEach((selectionItem) => {
|
||||
const item = selectionItem[0].context.item;
|
||||
const layoutItem = selectionItem[0].context.layoutItem;
|
||||
if (item && this.isItemType('subobject-view', layoutItem)) {
|
||||
subObjects.push(item);
|
||||
itemStyle = getApplicableStylesForItem(item);
|
||||
if (!this.isStaticAndConditionalStyles) {
|
||||
this.isStaticAndConditionalStyles = this.hasConditionalStyles(item);
|
||||
}
|
||||
} else {
|
||||
domainObject = selectionItem[1].context.item;
|
||||
itemStyle = getApplicableStylesForItem(domainObject, layoutItem || item);
|
||||
this.items.push({
|
||||
id: layoutItem.id,
|
||||
applicableStyles: itemStyle
|
||||
});
|
||||
if (!this.isStaticAndConditionalStyles) {
|
||||
this.isStaticAndConditionalStyles = this.hasConditionalStyles(domainObject, layoutItem.id);
|
||||
}
|
||||
}
|
||||
|
||||
itemInitialStyles.push(itemStyle);
|
||||
});
|
||||
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) {
|
||||
//check that all items that have been styles still exist. Otherwise delete those styles
|
||||
let keys = Object.keys(this.domainObject.configuration.objectStyles || {});
|
||||
keys.forEach((key) => {
|
||||
if ((key !== 'styles')
|
||||
&& (key !== 'staticStyle')
|
||||
&& (key !== 'conditionSetIdentifier')) {
|
||||
if (!(newItems.find(item => item.id === key))) {
|
||||
this.removeItemStyles(key);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
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, '*', function (newObject) {
|
||||
this.domainObjectsById[id] = JSON.parse(JSON.stringify(newObject));
|
||||
}.bind(this));
|
||||
this.unObserveObjects.push(unobserveObject);
|
||||
},
|
||||
removeListeners() {
|
||||
if (this.stopObserving) {
|
||||
this.stopObserving();
|
||||
}
|
||||
|
||||
if (this.stopObservingItems) {
|
||||
this.stopObservingItems();
|
||||
}
|
||||
|
||||
if (this.unObserveObjects) {
|
||||
this.unObserveObjects.forEach((unObserveObject) => {
|
||||
unObserveObject();
|
||||
});
|
||||
}
|
||||
|
||||
this.unObserveObjects = [];
|
||||
},
|
||||
removeItemStyles(itemId) {
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
if (itemId && domainObjectStyles[itemId]) {
|
||||
domainObjectStyles[itemId] = undefined;
|
||||
delete domainObjectStyles[this.itemId];
|
||||
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
|
||||
this.persist(this.domainObject, domainObjectStyles);
|
||||
}
|
||||
},
|
||||
removeConditionalStyles(domainObjectStyles, itemId) {
|
||||
if (itemId) {
|
||||
domainObjectStyles[itemId].conditionSetIdentifier = undefined;
|
||||
delete domainObjectStyles[itemId].conditionSetIdentifier;
|
||||
domainObjectStyles[itemId].styles = undefined;
|
||||
delete domainObjectStyles[itemId].styles;
|
||||
} else {
|
||||
domainObjectStyles.conditionSetIdentifier = undefined;
|
||||
delete domainObjectStyles.conditionSetIdentifier;
|
||||
domainObjectStyles.styles = undefined;
|
||||
delete domainObjectStyles.styles;
|
||||
}
|
||||
},
|
||||
setEditState(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
},
|
||||
initializeStaticStyle() {
|
||||
this.staticStyle = {
|
||||
style: Object.assign({}, this.initialStyles)
|
||||
};
|
||||
},
|
||||
updateStaticStyle(staticStyle, property) {
|
||||
//update the static style for each of the layoutItems as well as each sub object item
|
||||
this.staticStyle = staticStyle;
|
||||
this.persist(this.domainObject, this.getDomainObjectStyle(this.domainObject, property, this.items));
|
||||
if (this.domainObjectsById) {
|
||||
const keys = Object.keys(this.domainObjectsById);
|
||||
keys.forEach(key => {
|
||||
let domainObject = this.domainObjectsById[key];
|
||||
this.persist(domainObject, this.getDomainObjectStyle(domainObject, property));
|
||||
});
|
||||
}
|
||||
|
||||
this.isStaticAndConditionalStyles = false;
|
||||
let foundIndex = this.mixedStyles.indexOf(property);
|
||||
if (foundIndex > -1) {
|
||||
this.mixedStyles.splice(foundIndex, 1);
|
||||
}
|
||||
},
|
||||
getDomainObjectStyle(domainObject, property, items) {
|
||||
let domainObjectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
|
||||
|
||||
if (items) {
|
||||
items.forEach(item => {
|
||||
let itemStaticStyle = {};
|
||||
if (domainObjectStyles[item.id] && domainObjectStyles[item.id].staticStyle) {
|
||||
itemStaticStyle = domainObjectStyles[item.id].staticStyle.style;
|
||||
}
|
||||
|
||||
Object.keys(item.applicableStyles).forEach(key => {
|
||||
if (property === key) {
|
||||
itemStaticStyle[key] = this.staticStyle.style[key];
|
||||
}
|
||||
});
|
||||
if (this.isStaticAndConditionalStyles) {
|
||||
this.removeConditionalStyles(domainObjectStyles, item.id);
|
||||
}
|
||||
|
||||
if (isEmpty(itemStaticStyle)) {
|
||||
itemStaticStyle = undefined;
|
||||
domainObjectStyles[item.id] = undefined;
|
||||
} else {
|
||||
domainObjectStyles[item.id] = Object.assign({}, { staticStyle: { style: itemStaticStyle } });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!domainObjectStyles.staticStyle) {
|
||||
domainObjectStyles.staticStyle = {
|
||||
style: {}
|
||||
};
|
||||
}
|
||||
|
||||
if (this.isStaticAndConditionalStyles) {
|
||||
this.removeConditionalStyles(domainObjectStyles);
|
||||
}
|
||||
|
||||
domainObjectStyles.staticStyle.style[property] = this.staticStyle.style[property];
|
||||
}
|
||||
|
||||
return domainObjectStyles;
|
||||
},
|
||||
|
||||
persist(domainObject, style) {
|
||||
this.openmct.objects.mutate(domainObject, 'configuration.objectStyles', style);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -63,7 +63,7 @@
|
||||
<div class="c-inspect-styles__header">
|
||||
Conditional Object Styles
|
||||
</div>
|
||||
<div class="c-inspect-styles__content c-inspect-styles__condition-set c-inspect-styles__elem">
|
||||
<div class="c-inspect-styles__content c-inspect-styles__condition-set">
|
||||
<a v-if="conditionSetDomainObject"
|
||||
class="c-object-label"
|
||||
@click="navigateOrPreview"
|
||||
@ -87,27 +87,6 @@
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="isConditionWidget && allowEditing"
|
||||
class="c-inspect-styles__elem c-inspect-styles__output-label-toggle"
|
||||
>
|
||||
<label class="c-toggle-switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="useConditionSetOutputAsLabel"
|
||||
@change="updateConditionSetOutputLabel"
|
||||
>
|
||||
<span class="c-toggle-switch__slider"></span>
|
||||
<span class="c-toggle-switch__label">Use Condition Set output as label</span>
|
||||
</label>
|
||||
</div>
|
||||
<div v-if="isConditionWidget && !allowEditing"
|
||||
class="c-inspect-styles__elem"
|
||||
>
|
||||
<span class="c-toggle-switch__label">Condition Set output as label:
|
||||
<span v-if="useConditionSetOutputAsLabel"> Yes</span><span v-else> No</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<FontStyleEditor
|
||||
v-if="canStyleFont"
|
||||
:font-style="consolidatedFontStyle"
|
||||
@ -193,8 +172,7 @@ export default {
|
||||
selectedConditionId: '',
|
||||
items: [],
|
||||
domainObject: undefined,
|
||||
consolidatedFontStyle: {},
|
||||
useConditionSetOutputAsLabel: false
|
||||
consolidatedFontStyle: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -209,11 +187,6 @@ export default {
|
||||
allowEditing() {
|
||||
return this.isEditing && !this.locked;
|
||||
},
|
||||
isConditionWidget() {
|
||||
const hasConditionWidgetObjects = this.domainObjectsById && Object.values(this.domainObjectsById).some((object) => object.type === 'conditionWidget');
|
||||
|
||||
return (hasConditionWidgetObjects || (this.domainObject && this.domainObject.type === 'conditionWidget'));
|
||||
},
|
||||
styleableFontItems() {
|
||||
return this.selection.filter(selectionPath => {
|
||||
const item = selectionPath[0].context.item;
|
||||
@ -232,6 +205,28 @@ export default {
|
||||
return true;
|
||||
});
|
||||
},
|
||||
computedconsolidatedFontStyle() {
|
||||
let consolidatedFontStyle;
|
||||
const styles = [];
|
||||
|
||||
this.styleableFontItems.forEach(styleable => {
|
||||
const fontStyle = this.getFontStyle(styleable[0]);
|
||||
|
||||
styles.push(fontStyle);
|
||||
});
|
||||
|
||||
if (styles.length) {
|
||||
const hasConsolidatedFontSize = styles.length && styles.every((fontStyle, i, arr) => fontStyle.fontSize === arr[0].fontSize);
|
||||
const hasConsolidatedFont = styles.length && styles.every((fontStyle, i, arr) => fontStyle.font === arr[0].font);
|
||||
|
||||
consolidatedFontStyle = {
|
||||
fontSize: hasConsolidatedFontSize ? styles[0].fontSize : NON_SPECIFIC,
|
||||
font: hasConsolidatedFont ? styles[0].font : NON_SPECIFIC
|
||||
};
|
||||
}
|
||||
|
||||
return consolidatedFontStyle;
|
||||
},
|
||||
nonSpecificFontProperties() {
|
||||
if (!this.consolidatedFontStyle) {
|
||||
return [];
|
||||
@ -252,8 +247,6 @@ export default {
|
||||
this.previewAction = new PreviewAction(this.openmct);
|
||||
this.isMultipleSelection = this.selection.length > 1;
|
||||
this.getObjectsAndItemsFromSelection();
|
||||
this.useConditionSetOutputAsLabel = this.getConfigurationForLabel();
|
||||
|
||||
if (!this.isMultipleSelection) {
|
||||
let objectStyles = this.getObjectStyles();
|
||||
this.initializeStaticStyle(objectStyles);
|
||||
@ -271,12 +264,6 @@ export default {
|
||||
this.stylesManager.on('styleSelected', this.applyStyleToSelection);
|
||||
},
|
||||
methods: {
|
||||
getConfigurationForLabel() {
|
||||
const childObjectUsesLabels = Object.values(this.domainObjectsById || {}).some((object) => object.configuration && object.configuration.useConditionSetOutputAsLabel);
|
||||
const domainObjectUsesLabels = this.domainObject && this.domainObject.configuration && this.domainObject.configuration.useConditionSetOutputAsLabel;
|
||||
|
||||
return childObjectUsesLabels || domainObjectUsesLabels;
|
||||
},
|
||||
getObjectStyles() {
|
||||
let objectStyles;
|
||||
if (this.domainObjectsById) {
|
||||
@ -500,14 +487,13 @@ export default {
|
||||
|
||||
this.conditions[conditionConfiguration.id] = conditionConfiguration;
|
||||
let foundStyle = this.findStyleByConditionId(conditionConfiguration.id);
|
||||
let output = { output: conditionConfiguration.configuration.output };
|
||||
if (foundStyle) {
|
||||
foundStyle.style = Object.assign((this.canHide ? { isStyleInvisible: '' } : {}), this.initialStyles, foundStyle.style, output);
|
||||
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, output)
|
||||
style: Object.assign((this.canHide ? { isStyleInvisible: '' } : {}), this.initialStyles)
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -729,12 +715,6 @@ export default {
|
||||
} else {
|
||||
objectStyle.styles.forEach((conditionalStyle, index) => {
|
||||
let style = {};
|
||||
if (domainObject.configuration.useConditionSetOutputAsLabel) {
|
||||
style.output = conditionalStyle.style.output;
|
||||
} else {
|
||||
style.output = '';
|
||||
}
|
||||
|
||||
Object.keys(item.applicableStyles).concat(['isStyleInvisible']).forEach(key => {
|
||||
style[key] = conditionalStyle.style[key];
|
||||
});
|
||||
@ -751,21 +731,10 @@ export default {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (domainObject.configuration.useConditionSetOutputAsLabel !== true) {
|
||||
let objectConditionStyle = JSON.parse(JSON.stringify(objectStyle));
|
||||
objectConditionStyle.styles.forEach((conditionalStyle) => {
|
||||
conditionalStyle.style.output = '';
|
||||
});
|
||||
domainObjectStyles = {
|
||||
...domainObjectStyles,
|
||||
...objectConditionStyle
|
||||
};
|
||||
} else {
|
||||
domainObjectStyles = {
|
||||
...domainObjectStyles,
|
||||
...objectStyle
|
||||
};
|
||||
}
|
||||
domainObjectStyles = {
|
||||
...domainObjectStyles,
|
||||
...objectStyle
|
||||
};
|
||||
}
|
||||
|
||||
return domainObjectStyles;
|
||||
@ -774,17 +743,6 @@ export default {
|
||||
this.selectedConditionId = conditionId;
|
||||
this.getAndPersistStyles();
|
||||
},
|
||||
persistLabelConfiguration() {
|
||||
if (this.domainObjectsById) {
|
||||
Object.values(this.domainObjectsById).forEach((object) => {
|
||||
this.openmct.objects.mutate(object, 'configuration.useConditionSetOutputAsLabel', this.useConditionSetOutputAsLabel);
|
||||
});
|
||||
} else {
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration.useConditionSetOutputAsLabel', this.useConditionSetOutputAsLabel);
|
||||
}
|
||||
|
||||
this.getAndPersistStyles();
|
||||
},
|
||||
persist(domainObject, style) {
|
||||
this.openmct.objects.mutate(domainObject, 'configuration.objectStyles', style);
|
||||
},
|
||||
@ -905,10 +863,6 @@ export default {
|
||||
const layoutItemType = selectionPath[0].context.layoutItem && selectionPath[0].context.layoutItem.type;
|
||||
|
||||
return layoutItemType && layoutItemType !== 'subobject-view';
|
||||
},
|
||||
updateConditionSetOutputLabel(event) {
|
||||
this.useConditionSetOutputAsLabel = event.target.checked === true;
|
||||
this.persistLabelConfiguration();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -39,15 +39,12 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__elem {
|
||||
border-bottom: 1px solid $colorInteriorBorder;
|
||||
padding-bottom: $interiorMargin;
|
||||
}
|
||||
|
||||
&__condition-set {
|
||||
align-items: baseline;
|
||||
border-bottom: 1px solid $colorInteriorBorder;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-bottom: $interiorMargin;
|
||||
|
||||
.c-object-label {
|
||||
flex: 1 1 auto;
|
||||
|
@ -133,168 +133,6 @@ describe('the plugin', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('the condition set usage for condition widgets', () => {
|
||||
let conditionWidgetItem;
|
||||
let selection;
|
||||
let component;
|
||||
let styleViewComponentObject;
|
||||
const conditionSetDomainObject = {
|
||||
"configuration": {
|
||||
"conditionTestData": [
|
||||
{
|
||||
"telemetry": "",
|
||||
"metadata": "",
|
||||
"input": ""
|
||||
}
|
||||
],
|
||||
"conditionCollection": [
|
||||
{
|
||||
"id": "39584410-cbf9-499e-96dc-76f27e69885d",
|
||||
"configuration": {
|
||||
"name": "Unnamed Condition",
|
||||
"output": "Sine > 0",
|
||||
"trigger": "all",
|
||||
"criteria": [
|
||||
{
|
||||
"id": "85fbb2f7-7595-42bd-9767-a932266c5225",
|
||||
"telemetry": {
|
||||
"namespace": "",
|
||||
"key": "be0ba97f-b510-4f40-a18d-4ff121d5ea1a"
|
||||
},
|
||||
"operation": "greaterThan",
|
||||
"input": [
|
||||
"0"
|
||||
],
|
||||
"metadata": "sin"
|
||||
},
|
||||
{
|
||||
"id": "35400132-63b0-425c-ac30-8197df7d5862",
|
||||
"telemetry": "any",
|
||||
"operation": "enumValueIs",
|
||||
"input": [
|
||||
"0"
|
||||
],
|
||||
"metadata": "state"
|
||||
}
|
||||
]
|
||||
},
|
||||
"summary": "Match if all criteria are met: Sine Wave Generator Sine > 0 and any telemetry State is OFF "
|
||||
},
|
||||
{
|
||||
"isDefault": true,
|
||||
"id": "2532d90a-e0d6-4935-b546-3123522da2de",
|
||||
"configuration": {
|
||||
"name": "Default",
|
||||
"output": "Default",
|
||||
"trigger": "all",
|
||||
"criteria": [
|
||||
]
|
||||
},
|
||||
"summary": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"composition": [
|
||||
{
|
||||
"namespace": "",
|
||||
"key": "be0ba97f-b510-4f40-a18d-4ff121d5ea1a"
|
||||
},
|
||||
{
|
||||
"namespace": "",
|
||||
"key": "077ffa67-e78f-4e99-80e0-522ac33a3888"
|
||||
}
|
||||
],
|
||||
"telemetry": {
|
||||
},
|
||||
"name": "Condition Set",
|
||||
"type": "conditionSet",
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "863012c1-f6ca-4ab0-aed7-fd43d5e4cd12"
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
conditionWidgetItem = {
|
||||
"label": "Condition Widget",
|
||||
"conditionalLabel": "",
|
||||
"configuration": {
|
||||
},
|
||||
"name": "Condition Widget",
|
||||
"type": "conditionWidget",
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "c5e636c1-6771-4c9c-b933-8665cab189b3"
|
||||
}
|
||||
};
|
||||
selection = [
|
||||
[{
|
||||
context: {
|
||||
"item": conditionWidgetItem,
|
||||
"supportsMultiSelect": false
|
||||
}
|
||||
}]
|
||||
];
|
||||
let viewContainer = document.createElement('div');
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
components: {
|
||||
StylesView
|
||||
},
|
||||
provide: {
|
||||
openmct: openmct,
|
||||
selection: selection,
|
||||
stylesManager
|
||||
},
|
||||
template: '<styles-view/>'
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
styleViewComponentObject = component.$root.$children[0];
|
||||
styleViewComponentObject.setEditState(true);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
component.$destroy();
|
||||
});
|
||||
|
||||
it('does not include the output label when the flag is disabled', () => {
|
||||
styleViewComponentObject.conditionSetDomainObject = conditionSetDomainObject;
|
||||
styleViewComponentObject.conditionalStyles = [];
|
||||
styleViewComponentObject.initializeConditionalStyles();
|
||||
expect(styleViewComponentObject.conditionalStyles.length).toBe(2);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
const hasNoOutput = styleViewComponentObject.domainObject.configuration.objectStyles.styles.every((style) => {
|
||||
return style.style.output === '' || style.style.output === undefined;
|
||||
});
|
||||
|
||||
expect(hasNoOutput).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
it('includes the output label when the flag is enabled', () => {
|
||||
styleViewComponentObject.conditionSetDomainObject = conditionSetDomainObject;
|
||||
styleViewComponentObject.conditionalStyles = [];
|
||||
styleViewComponentObject.initializeConditionalStyles();
|
||||
expect(styleViewComponentObject.conditionalStyles.length).toBe(2);
|
||||
|
||||
styleViewComponentObject.useConditionSetOutputAsLabel = true;
|
||||
styleViewComponentObject.persistLabelConfiguration();
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
const outputs = styleViewComponentObject.domainObject.configuration.objectStyles.styles.map((style) => {
|
||||
return style.style.output;
|
||||
});
|
||||
expect(outputs.join(',')).toEqual('Sine > 0,Default');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('the condition set usage for multiple display layout items', () => {
|
||||
let displayLayoutItem;
|
||||
let lineLayoutItem;
|
||||
@ -611,10 +449,6 @@ describe('the plugin', function () {
|
||||
const applicableStyles = getApplicableStylesForItem(styleViewComponentObject.domainObject, item);
|
||||
const applicableStylesKeys = Object.keys(applicableStyles).concat(['isStyleInvisible']);
|
||||
Object.keys(foundStyle.style).forEach((key) => {
|
||||
if (key === 'output') {
|
||||
return;
|
||||
}
|
||||
|
||||
expect(applicableStylesKeys.indexOf(key)).toBeGreaterThan(-1);
|
||||
expect(foundStyle.style[key]).toEqual(conditionalStyle.style[key]);
|
||||
});
|
||||
|
@ -26,7 +26,7 @@
|
||||
:href="url"
|
||||
>
|
||||
<div class="c-condition-widget__label">
|
||||
{{ internalDomainObject.conditionalLabel || internalDomainObject.label }}
|
||||
{{ internalDomainObject.label }}
|
||||
</div>
|
||||
</component>
|
||||
</template>
|
||||
|
@ -27,15 +27,12 @@ export default function plugin() {
|
||||
openmct.objectViews.addProvider(new ConditionWidgetViewProvider(openmct));
|
||||
|
||||
openmct.types.addType('conditionWidget', {
|
||||
key: 'conditionWidget',
|
||||
name: "Condition Widget",
|
||||
description: "A button that can be used on its own, or dynamically styled with a Condition Set.",
|
||||
creatable: true,
|
||||
cssClass: 'icon-condition-widget',
|
||||
initialize(domainObject) {
|
||||
domainObject.configuration = {};
|
||||
domainObject.label = 'Condition Widget';
|
||||
domainObject.conditionalLabel = '';
|
||||
},
|
||||
form: [
|
||||
{
|
||||
|
@ -1,195 +0,0 @@
|
||||
import { createOpenMct, resetApplicationState } from "utils/testing";
|
||||
import ConditionWidgetPlugin from "./plugin";
|
||||
import Vue from 'vue';
|
||||
|
||||
describe('the plugin', function () {
|
||||
const CONDITION_WIDGET_KEY = 'conditionWidget';
|
||||
let objectDef;
|
||||
let element;
|
||||
let child;
|
||||
let openmct;
|
||||
let mockConditionObjectDefinition;
|
||||
let mockConditionObject;
|
||||
let mockConditionObjectPath;
|
||||
|
||||
beforeEach((done) => {
|
||||
mockConditionObjectPath = [
|
||||
{
|
||||
name: 'mock folder',
|
||||
type: 'fake-folder',
|
||||
identifier: {
|
||||
key: 'mock-folder',
|
||||
namespace: ''
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'mock parent folder',
|
||||
type: 'conditionWidget',
|
||||
identifier: {
|
||||
key: 'mock-parent-folder',
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
mockConditionObjectDefinition = {
|
||||
name: 'Condition Widget',
|
||||
key: 'conditionWidget',
|
||||
creatable: true
|
||||
};
|
||||
|
||||
mockConditionObject = {
|
||||
"conditionWidget": {
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "condition-widget-object"
|
||||
},
|
||||
"url": "https://nasa.github.io/openmct/",
|
||||
"label": "Foo Widget",
|
||||
"type": "conditionWidget",
|
||||
"composition": []
|
||||
},
|
||||
"telemetry": {
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "telemetry-object"
|
||||
},
|
||||
"type": "test-telemetry-object",
|
||||
"name": "Test Telemetry Object",
|
||||
"telemetry": {
|
||||
"values": [
|
||||
{
|
||||
"key": "name",
|
||||
"name": "Name",
|
||||
"format": "string"
|
||||
},
|
||||
{
|
||||
"key": "utc",
|
||||
"name": "Time",
|
||||
"format": "utc",
|
||||
"hints": {
|
||||
"domain": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Some attribute 1",
|
||||
"key": "some-key-1",
|
||||
"hints": {
|
||||
"range": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Some attribute 2",
|
||||
"key": "some-key-2"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const timeSystem = {
|
||||
timeSystemKey: 'utc',
|
||||
bounds: {
|
||||
start: 1597160002854,
|
||||
end: 1597181232854
|
||||
}
|
||||
};
|
||||
|
||||
openmct = createOpenMct(timeSystem);
|
||||
openmct.install(new ConditionWidgetPlugin());
|
||||
|
||||
objectDef = openmct.types.get('conditionWidget').definition;
|
||||
|
||||
element = document.createElement('div');
|
||||
element.style.width = '640px';
|
||||
element.style.height = '480px';
|
||||
child = document.createElement('div');
|
||||
child.style.width = '640px';
|
||||
child.style.height = '480px';
|
||||
element.appendChild(child);
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
return resetApplicationState(openmct);
|
||||
});
|
||||
|
||||
it('defines a conditionWidget object type with the correct key', () => {
|
||||
expect(objectDef.key).toEqual(mockConditionObjectDefinition.key);
|
||||
});
|
||||
|
||||
describe('the conditionWidget object', () => {
|
||||
it('is creatable', () => {
|
||||
expect(objectDef.creatable).toEqual(mockConditionObjectDefinition.creatable);
|
||||
});
|
||||
});
|
||||
|
||||
describe('the view', () => {
|
||||
let conditionWidgetView;
|
||||
let testViewObject;
|
||||
|
||||
beforeEach(() => {
|
||||
testViewObject = {
|
||||
id: "test-object",
|
||||
identifier: {
|
||||
key: "test-object",
|
||||
namespace: ''
|
||||
},
|
||||
type: "conditionWidget"
|
||||
};
|
||||
|
||||
const applicableViews = openmct.objectViews.get(testViewObject, mockConditionObjectPath);
|
||||
conditionWidgetView = applicableViews.find((viewProvider) => viewProvider.key === 'conditionWidget');
|
||||
let view = conditionWidgetView.view(testViewObject, element);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
});
|
||||
|
||||
it('provides a view', () => {
|
||||
expect(conditionWidgetView).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
it("should have a view provider for condition widget objects", () => {
|
||||
const applicableViews = openmct.objectViews.get(mockConditionObject[CONDITION_WIDGET_KEY], []);
|
||||
|
||||
const conditionWidgetViewProvider = applicableViews.find(
|
||||
(viewProvider) => viewProvider.key === CONDITION_WIDGET_KEY
|
||||
);
|
||||
|
||||
expect(applicableViews.length).toEqual(1);
|
||||
expect(conditionWidgetViewProvider).toBeDefined();
|
||||
});
|
||||
|
||||
it("should render a view with a URL and label", async () => {
|
||||
const urlParent = document.createElement('div');
|
||||
const urlChild = document.createElement('div');
|
||||
urlParent.appendChild(urlChild);
|
||||
|
||||
const applicableViews = openmct.objectViews.get(mockConditionObject[CONDITION_WIDGET_KEY], []);
|
||||
|
||||
const conditionWidgetViewProvider = applicableViews.find(
|
||||
(viewProvider) => viewProvider.key === CONDITION_WIDGET_KEY
|
||||
);
|
||||
|
||||
const conditionWidgetView = conditionWidgetViewProvider.view(mockConditionObject[CONDITION_WIDGET_KEY], [mockConditionObject[CONDITION_WIDGET_KEY]]);
|
||||
conditionWidgetView.show(urlChild);
|
||||
|
||||
await Vue.nextTick();
|
||||
|
||||
const domainUrl = mockConditionObject[CONDITION_WIDGET_KEY].url;
|
||||
expect(urlParent.innerHTML).toContain(`<a href="${domainUrl}"`);
|
||||
|
||||
const conditionWidgetRender = urlParent.querySelector('.c-condition-widget');
|
||||
expect(conditionWidgetRender).toBeDefined();
|
||||
expect(conditionWidgetRender.innerHTML).toContain('<div class="c-condition-widget__label">');
|
||||
|
||||
const conditionWidgetLabel = conditionWidgetRender.querySelector('.c-condition-widget__label');
|
||||
expect(conditionWidgetLabel).toBeDefined();
|
||||
const domainLabel = mockConditionObject[CONDITION_WIDGET_KEY].label;
|
||||
expect(conditionWidgetLabel.textContent).toContain(domainLabel);
|
||||
});
|
||||
});
|
@ -38,14 +38,10 @@ export default {
|
||||
this.objectStyle = this.getObjectStyleForItem(this.parentDomainObject.configuration.objectStyles);
|
||||
this.initObjectStyles();
|
||||
},
|
||||
beforeDestroy() {
|
||||
destroyed() {
|
||||
if (this.stopListeningObjectStyles) {
|
||||
this.stopListeningObjectStyles();
|
||||
}
|
||||
|
||||
if (this.styleRuleManager) {
|
||||
this.styleRuleManager.destroy();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getObjectStyleForItem(objectStyle) {
|
||||
|
@ -175,7 +175,7 @@ export default {
|
||||
focusEntryId: null,
|
||||
search: '',
|
||||
searchResults: [],
|
||||
showTime: this.domainObject.configuration.showTime || 0,
|
||||
showTime: 0,
|
||||
showNav: false,
|
||||
sidebarCoversEntries: false
|
||||
};
|
||||
@ -239,12 +239,6 @@ export default {
|
||||
watch: {
|
||||
search() {
|
||||
this.getSearchResults();
|
||||
},
|
||||
defaultSort() {
|
||||
mutateObject(this.openmct, this.domainObject, 'configuration.defaultSort', this.defaultSort);
|
||||
},
|
||||
showTime() {
|
||||
mutateObject(this.openmct, this.domainObject, 'configuration.showTime', this.showTime);
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
@ -185,11 +185,6 @@
|
||||
&__inputs,
|
||||
&__time-bounds {
|
||||
display: flex;
|
||||
|
||||
.c-toggle-switch {
|
||||
// Used in independent Time Conductor
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__inputs {
|
||||
|
@ -1,45 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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.
|
||||
*
|
||||
* Open MCT https://nasa.github.io/openmct/
|
||||
* Version: @@version
|
||||
* Built: @@timestamp
|
||||
* Revision: @@revision
|
||||
* Branch: @@branch
|
||||
*
|
||||
* @preserve
|
||||
*****************************************************************************/
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.openmct = factory();
|
||||
}
|
||||
}(this, function() {
|
||||
var BUILD_CONSTANTS = {
|
||||
version: "@@version",
|
||||
timestamp: "@@timestamp",
|
||||
revision: "@@revision",
|
||||
branch: "@@branch"
|
||||
};
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
export const COLOR_PALETTE = [
|
||||
[0x43, 0xB0, 0xFF],
|
||||
[0x00, 0x37, 0xFF],
|
||||
[0xF0, 0x60, 0x00],
|
||||
[0x00, 0x70, 0x40],
|
||||
[0xFB, 0x49, 0x49],
|
||||
@ -30,25 +30,25 @@ export const COLOR_PALETTE = [
|
||||
[0xFF, 0xA6, 0x3D],
|
||||
[0x05, 0xA3, 0x00],
|
||||
[0xF0, 0x00, 0x6C],
|
||||
[0xAC, 0x54, 0xAE],
|
||||
[0x77, 0x17, 0x7A],
|
||||
[0x23, 0xA9, 0xDB],
|
||||
[0xC7, 0xBE, 0x52],
|
||||
[0x5A, 0xBD, 0x56],
|
||||
[0xFA, 0xF0, 0x6F],
|
||||
[0x4E, 0xF0, 0x48],
|
||||
[0xAD, 0x50, 0x72],
|
||||
[0x94, 0x25, 0xEA],
|
||||
[0x21, 0x87, 0x82],
|
||||
[0x8F, 0x6E, 0x47],
|
||||
[0xf0, 0x59, 0xcb],
|
||||
[0x34, 0xB6, 0x7D],
|
||||
[0x7F, 0x52, 0xFF],
|
||||
[0x46, 0xC7, 0xC0],
|
||||
[0x6A, 0x36, 0xFF],
|
||||
[0x56, 0xF0, 0xE8],
|
||||
[0xA1, 0x8C, 0x1C],
|
||||
[0x95, 0xB1, 0x26],
|
||||
[0xCB, 0xE1, 0x44],
|
||||
[0xFF, 0x84, 0x9E],
|
||||
[0xB7, 0x79, 0xE7],
|
||||
[0x8C, 0xC9, 0xFD],
|
||||
[0xDB, 0xAA, 0x6E],
|
||||
[0x93, 0xB5, 0x77],
|
||||
[0xB8, 0xDF, 0x97],
|
||||
[0xFF, 0xBC, 0xDA],
|
||||
[0xD3, 0xB6, 0xDE]
|
||||
];
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="supportsIndependentTime"
|
||||
<div v-if="domainObject && domainObject.type === 'time-strip'"
|
||||
class="c-conductor-holder--compact l-shell__main-independent-time-conductor"
|
||||
>
|
||||
<independent-time-conductor :domain-object="domainObject"
|
||||
@ -20,12 +20,6 @@ import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
|
||||
import {STYLE_CONSTANTS} from "@/plugins/condition/utils/constants";
|
||||
import IndependentTimeConductor from '@/plugins/timeConductor/independent/IndependentTimeConductor.vue';
|
||||
|
||||
const SupportedViewTypes = [
|
||||
'plot-stacked',
|
||||
'plot-overlay',
|
||||
'bar-graph.view',
|
||||
'time-strip.view'
|
||||
];
|
||||
export default {
|
||||
components: {
|
||||
IndependentTimeConductor
|
||||
@ -70,11 +64,6 @@ export default {
|
||||
},
|
||||
font() {
|
||||
return this.objectFontStyle ? this.objectFontStyle.font : this.layoutFont;
|
||||
},
|
||||
supportsIndependentTime() {
|
||||
const viewKey = this.getViewKey();
|
||||
|
||||
return this.domainObject && SupportedViewTypes.includes(viewKey);
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
@ -202,12 +191,6 @@ export default {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.domainObject && this.domainObject.type === 'conditionWidget' && keys.includes('output')) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'conditionalLabel', styleObj.output);
|
||||
} else {
|
||||
this.openmct.objects.mutate(this.domainObject, 'conditionalLabel', '');
|
||||
}
|
||||
},
|
||||
updateView(immediatelySelect) {
|
||||
this.clear();
|
||||
|
@ -1,13 +0,0 @@
|
||||
/* Note: Open MCT does not intend to support the entire Typescript ecosystem at this time.
|
||||
* This file is intended to add Intellisense for IDEs like VSCode. For more information
|
||||
* about Typescript, please discuss in https://github.com/nasa/openmct/discussions/4693
|
||||
*/
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"strict": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node"
|
||||
}
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
/* global __dirname */
|
||||
|
||||
const path = require('path');
|
||||
const packageDefinition = require('./package.json');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
@ -14,8 +12,7 @@ const gitBranch = require('child_process')
|
||||
.execSync('git rev-parse --abbrev-ref HEAD')
|
||||
.toString().trim();
|
||||
|
||||
/** @type {import('webpack').Configuration} */
|
||||
const config = {
|
||||
module.exports = {
|
||||
entry: {
|
||||
openmct: './openmct.js',
|
||||
couchDBChangesFeed: './src/plugins/persistence/couch/CouchChangesFeed.js',
|
||||
@ -30,7 +27,6 @@ const config = {
|
||||
library: '[name]',
|
||||
libraryTarget: 'umd',
|
||||
publicPath: '',
|
||||
hashFunction: 'xxhash64',
|
||||
clean: true
|
||||
},
|
||||
resolve: {
|
||||
@ -133,5 +129,3 @@ const config = {
|
||||
},
|
||||
stats: 'errors-warnings'
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
Reference in New Issue
Block a user