Compare commits

..

7 Commits

Author SHA1 Message Date
David Tsay
4b39e17565 Merge branch 'master' into hide-params 2021-08-13 13:49:53 -07:00
David Tsay
fd5631f5b7 do not constantly listen to param changes 2021-08-13 13:34:42 -07:00
David Tsay
d1dba4921b Merge branch 'master' into flexible-inspector-properties 2021-08-11 14:44:54 -07:00
David Tsay
42af3ad2fc re-org files for clarity 2021-07-14 14:11:13 -07:00
David Tsay
16fe1b55c6 bubble activity logic to parent 2021-07-13 17:06:11 -07:00
David Tsay
8037c372b0 add missing copyrights 2021-07-13 16:33:26 -07:00
David Tsay
216a349282 allow custom details while retaining current domain object details 2021-07-13 16:32:22 -07:00
113 changed files with 1823 additions and 2025 deletions

View File

@@ -56,38 +56,14 @@ workflows:
browser: ChromeHeadless
always-pass: false
- test:
name: node12-firefoxESR-build-only
name: node12-firefoxESR
node-version: lts/erbium
browser: FirefoxESR
always-pass: true
- test:
name: node14-chrome-build-only
name: node14-chrome
node-version: lts/fermium
browser: ChromeHeadless
always-pass: true
nightly:
jobs:
- test:
name: node10-chrome-nightly
node-version: lts/dubnium
browser: ChromeHeadless
always-pass: false
- test:
name: node12-firefoxESR-nightly
node-version: lts/erbium
browser: FirefoxESR
always-pass: false
- test:
name: node14-chrome-nightly
node-version: lts/fermium
browser: ChromeHeadless
always-pass: false
triggers:
- schedule:
cron: "0 0 * * *"
filters:
branches:
only:
- master

View File

@@ -1,33 +0,0 @@
name: "CodeQL"
on:
push:
branches: [ master ]
schedule:
- cron: '28 21 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

1
.npmrc
View File

@@ -1 +0,0 @@
loglevel=warn

2
API.md
View File

@@ -996,7 +996,7 @@ reveal additional information when the mouse cursor is hovered over it.
A common use case for indicators is to convey the state of some external system such as a
persistence backend or HTTP server. So long as this system is accessible via HTTP request,
Open MCT provides a general purpose indicator to show whether the server is available and
returning a 2xx status code. The URL Status Indicator is made available as a default plugin. See
returing a 2xx status code. The URL Status Indicator is made available as a default plugin. See
the [documentation](./src/plugins/URLIndicatorPlugin) for details on how to install and configure the
URL Status Indicator.

View File

@@ -423,7 +423,7 @@ which can help with this, however.
instead of separate approaches for static and substitutable
dependencies.
* Removes need to understand Angular's DI mechanism.
* Improves usability of documentation (`typeService` is an
* Improves useability of documentation (`typeService` is an
instance of `CompositeService` and implements `TypeService`
so you can easily traverse links in the JSDoc.)
* Can be used more easily from Web Workers, allowing services

View File

@@ -25,7 +25,7 @@
## Legacy Documentation
As we transition to a new API, the following documentation for the old API
(which is supported during the transition) may be useful as well:
(which is supported during the transtion) may be useful as well:
* The [Architecture Overview](architecture/) describes the concepts used
throughout Open MCT, and gives a high level overview of the platform's design.

View File

@@ -152,7 +152,7 @@
<h2>How to Use Glyphs</h2>
<div class="cols cols1-1">
<div class="col">
<p>The easiest way to use a glyph is to include its CSS class in an element. The CSS adds a pseudo <code>:before</code> HTML element to whatever element it's attached to that makes proper use of the symbols font.</p>
<p>The easiest way to use a glyph is to include its CSS class in an element. The CSS adds a psuedo <code>:before</code> HTML element to whatever element it's attached to that makes proper use of the symbols font.</p>
<p>Alternately, you can use the <code>.ui-symbol</code> class in an object that contains encoded HTML entities. This method is only recommended if you cannot use the aforementioned CSS class approach.</p>
</div>
<mct-example><a class="s-button icon-gear" title="Settings"></a>

View File

@@ -1,6 +1,6 @@
{
"name": "openmct",
"version": "1.7.8-SNAPSHOT",
"version": "1.7.6-SNAPSHOT",
"description": "The Open MCT core platform",
"dependencies": {},
"devDependencies": {

View File

@@ -64,7 +64,7 @@ define(
*
* @param {DomainObject} domainObject the domain object to navigate to
* @param {Boolean} force if true, force navigation to occur.
* @returns {Boolean} true if navigation occurred, otherwise false.
* @returns {Boolean} true if navigation occured, otherwise false.
*/
NavigationService.prototype.setNavigation = function (domainObject, force) {
if (force) {

View File

@@ -21,14 +21,28 @@
*****************************************************************************/
define([
"./src/AgentService"
"./src/MCTDevice",
"./src/AgentService",
"./src/DeviceClassifier"
], function (
AgentService
MCTDevice,
AgentService,
DeviceClassifier
) {
return {
name: "platform/commonUI/mobile",
definition: {
"extensions": {
"directives": [
{
"key": "mctDevice",
"implementation": MCTDevice,
"depends": [
"agentService"
]
}
],
"services": [
{
"key": "agentService",
@@ -37,6 +51,15 @@ define([
"$window"
]
}
],
"runs": [
{
"implementation": DeviceClassifier,
"depends": [
"agentService",
"$document"
]
}
]
}
}

View File

@@ -20,12 +20,122 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(["../../../../src/utils/agent/Agent.js"], function (Agent) {
function AngularAgentServiceWrapper(window) {
const AS = Agent.default;
/**
* Provides features which support variant behavior on mobile devices.
*
* @namespace platform/commonUI/mobile
*/
define(
[],
function () {
return new AS(window);
/**
* The query service handles calls for browser and userAgent
* info using a comparison between the userAgent and key
* device names
* @constructor
* @param $window Angular-injected instance of the window
* @memberof platform/commonUI/mobile
*/
function AgentService($window) {
var userAgent = $window.navigator.userAgent,
matches = userAgent.match(/iPad|iPhone|Android/i) || [];
this.userAgent = userAgent;
this.mobileName = matches[0];
this.$window = $window;
this.touchEnabled = ($window.ontouchstart !== undefined);
}
/**
* Check if the user is on a mobile device.
* @returns {boolean} true on mobile
*/
AgentService.prototype.isMobile = function () {
return Boolean(this.mobileName);
};
/**
* Check if the user is on a phone-sized mobile device.
* @returns {boolean} true on a phone
*/
AgentService.prototype.isPhone = function () {
if (this.isMobile()) {
if (this.isAndroidTablet()) {
return false;
} else if (this.mobileName === 'iPad') {
return false;
} else {
return true;
}
} else {
return false;
}
};
/**
* Check if the user is on a tablet sized android device
* @returns {boolean} true on an android tablet
*/
AgentService.prototype.isAndroidTablet = function () {
if (this.mobileName === 'Android') {
if (this.isPortrait() && window.innerWidth >= 768) {
return true;
} else if (this.isLandscape() && window.innerHeight >= 768) {
return true;
}
} else {
return false;
}
};
/**
* Check if the user is on a tablet-sized mobile device.
* @returns {boolean} true on a tablet
*/
AgentService.prototype.isTablet = function () {
return (this.isMobile() && !this.isPhone() && this.mobileName !== 'Android') || (this.isMobile() && this.isAndroidTablet());
};
/**
* Check if the user's device is in a portrait-style
* orientation (display width is narrower than display height.)
* @returns {boolean} true in portrait mode
*/
AgentService.prototype.isPortrait = function () {
return this.$window.innerWidth < this.$window.innerHeight;
};
/**
* Check if the user's device is in a landscape-style
* orientation (display width is greater than display height.)
* @returns {boolean} true in landscape mode
*/
AgentService.prototype.isLandscape = function () {
return !this.isPortrait();
};
/**
* Check if the user's device supports a touch interface.
* @returns {boolean} true if touch is supported
*/
AgentService.prototype.isTouch = function () {
return this.touchEnabled;
};
/**
* Check if the user agent matches a certain named device,
* as indicated by checking for a case-insensitive substring
* match.
* @param {string} name the name to check for
* @returns {boolean} true if the user agent includes that name
*/
AgentService.prototype.isBrowser = function (name) {
name = name.toLowerCase();
return this.userAgent.toLowerCase().indexOf(name) !== -1;
};
return AgentService;
}
return AngularAgentServiceWrapper;
});
);

View File

@@ -1,96 +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 AgentService from "./AgentService";
const TEST_USER_AGENTS = {
DESKTOP:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36",
IPAD:
"Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
IPHONE:
"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53"
};
describe("The AgentService", function () {
let testWindow;
let agentService;
beforeEach(function () {
testWindow = {
innerWidth: 640,
innerHeight: 480,
navigator: {
userAgent: TEST_USER_AGENTS.DESKTOP
}
};
});
it("recognizes desktop devices as non-mobile", function () {
testWindow.navigator.userAgent = TEST_USER_AGENTS.DESKTOP;
agentService = new AgentService(testWindow);
expect(agentService.isMobile()).toBeFalsy();
expect(agentService.isPhone()).toBeFalsy();
expect(agentService.isTablet()).toBeFalsy();
});
it("detects iPhones", function () {
testWindow.navigator.userAgent = TEST_USER_AGENTS.IPHONE;
agentService = new AgentService(testWindow);
expect(agentService.isMobile()).toBeTruthy();
expect(agentService.isPhone()).toBeTruthy();
expect(agentService.isTablet()).toBeFalsy();
});
it("detects iPads", function () {
testWindow.navigator.userAgent = TEST_USER_AGENTS.IPAD;
agentService = new AgentService(testWindow);
expect(agentService.isMobile()).toBeTruthy();
expect(agentService.isPhone()).toBeFalsy();
expect(agentService.isTablet()).toBeTruthy();
});
it("detects display orientation", function () {
agentService = new AgentService(testWindow);
testWindow.innerWidth = 1024;
testWindow.innerHeight = 400;
expect(agentService.isPortrait()).toBeFalsy();
expect(agentService.isLandscape()).toBeTruthy();
testWindow.innerWidth = 400;
testWindow.innerHeight = 1024;
expect(agentService.isPortrait()).toBeTruthy();
expect(agentService.isLandscape()).toBeFalsy();
});
it("detects touch support", function () {
testWindow.ontouchstart = null;
expect(new AgentService(testWindow).isTouch()).toBe(true);
delete testWindow.ontouchstart;
expect(new AgentService(testWindow).isTouch()).toBe(false);
});
it("allows for checking browser type", function () {
testWindow.navigator.userAgent = "Chromezilla Safarifox";
agentService = new AgentService(testWindow);
expect(agentService.isBrowser("Chrome")).toBe(true);
expect(agentService.isBrowser("Firefox")).toBe(false);
});
});

View File

@@ -0,0 +1,72 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define(
['./DeviceMatchers'],
function (DeviceMatchers) {
/**
* Runs at application startup and adds a subset of the following
* CSS classes to the body of the document, depending on device
* attributes:
*
* * `mobile`: Phones or tablets.
* * `phone`: Phones specifically.
* * `tablet`: Tablets specifically.
* * `desktop`: Non-mobile devices.
* * `portrait`: Devices in a portrait-style orientation.
* * `landscape`: Devices in a landscape-style orientation.
* * `touch`: Device supports touch events.
*
* @param {platform/commonUI/mobile.AgentService} agentService
* the service used to examine the user agent
* @param $document Angular's jqLite-wrapped document element
* @constructor
*/
function MobileClassifier(agentService, $document) {
var body = $document.find('body');
Object.keys(DeviceMatchers).forEach(function (key, index, array) {
if (DeviceMatchers[key](agentService)) {
body.addClass(key);
}
});
if (agentService.isMobile()) {
var mediaQuery = window.matchMedia('(orientation: landscape)');
mediaQuery.addListener(function (event) {
if (event.matches) {
body.removeClass('portrait');
body.addClass('landscape');
} else {
body.removeClass('landscape');
body.addClass('portrait');
}
});
}
}
return MobileClassifier;
}
);

View File

@@ -0,0 +1,58 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define(function () {
/**
* An object containing key-value pairs, where keys are symbolic of
* device attributes, and values are functions that take the
* `agentService` as inputs and return boolean values indicating
* whether or not the current device has these attributes.
*
* For internal use by the mobile support bundle.
*
* @memberof platform/commonUI/mobile
* @private
*/
return {
mobile: function (agentService) {
return agentService.isMobile();
},
phone: function (agentService) {
return agentService.isPhone();
},
tablet: function (agentService) {
return agentService.isTablet();
},
desktop: function (agentService) {
return !agentService.isMobile();
},
portrait: function (agentService) {
return agentService.isPortrait();
},
landscape: function (agentService) {
return agentService.isLandscape();
},
touch: function (agentService) {
return agentService.isTouch();
}
};
});

View File

@@ -0,0 +1,88 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define(
['./DeviceMatchers'],
function (DeviceMatchers) {
/**
* The `mct-device` directive, when applied as an attribute,
* only includes the element when the device being used matches
* a set of characteristics required.
*
* Required characteristics are given as space-separated strings
* as the value to this attribute, e.g.:
*
* <span mct-device="mobile portrait">Hello world!</span>
*
* ...will only show Hello world! when viewed on a mobile device
* in the portrait orientation.
*
* Valid device characteristics to detect are:
*
* * `mobile`: Phones or tablets.
* * `phone`: Phones specifically.
* * `tablet`: Tablets specifically.
* * `desktop`: Non-mobile devices.
* * `portrait`: Devices in a portrait-style orientation.
* * `landscape`: Devices in a landscape-style orientation.
* * `touch`: Device supports touch events.
*
* @param {AgentService} agentService used to detect device type
* based on information about the user agent
*/
function MCTDevice(agentService) {
function deviceMatches(tokens) {
tokens = tokens || "";
return tokens.split(" ").every(function (token) {
var fn = DeviceMatchers[token];
return fn && fn(agentService);
});
}
function link(scope, element, attrs, ctrl, transclude) {
if (deviceMatches(attrs.mctDevice)) {
transclude(function (clone) {
element.replaceWith(clone);
});
}
}
return {
link: link,
// We are transcluding the whole element (like ng-if)
transclude: 'element',
// 1 more than ng-if
priority: 601,
// Also terminal, since element will be transcluded
terminal: true,
// Only apply as an attribute
restrict: "A"
};
}
return MCTDevice;
}
);

View File

@@ -0,0 +1,99 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define(
["../src/AgentService"],
function (AgentService) {
var TEST_USER_AGENTS = {
DESKTOP: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36",
IPAD: "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
IPHONE: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53"
};
describe("The AgentService", function () {
var testWindow, agentService;
beforeEach(function () {
testWindow = {
innerWidth: 640,
innerHeight: 480,
navigator: {
userAgent: TEST_USER_AGENTS.DESKTOP
}
};
});
it("recognizes desktop devices as non-mobile", function () {
testWindow.navigator.userAgent = TEST_USER_AGENTS.DESKTOP;
agentService = new AgentService(testWindow);
expect(agentService.isMobile()).toBeFalsy();
expect(agentService.isPhone()).toBeFalsy();
expect(agentService.isTablet()).toBeFalsy();
});
it("detects iPhones", function () {
testWindow.navigator.userAgent = TEST_USER_AGENTS.IPHONE;
agentService = new AgentService(testWindow);
expect(agentService.isMobile()).toBeTruthy();
expect(agentService.isPhone()).toBeTruthy();
expect(agentService.isTablet()).toBeFalsy();
});
it("detects iPads", function () {
testWindow.navigator.userAgent = TEST_USER_AGENTS.IPAD;
agentService = new AgentService(testWindow);
expect(agentService.isMobile()).toBeTruthy();
expect(agentService.isPhone()).toBeFalsy();
expect(agentService.isTablet()).toBeTruthy();
});
it("detects display orientation", function () {
agentService = new AgentService(testWindow);
testWindow.innerWidth = 1024;
testWindow.innerHeight = 400;
expect(agentService.isPortrait()).toBeFalsy();
expect(agentService.isLandscape()).toBeTruthy();
testWindow.innerWidth = 400;
testWindow.innerHeight = 1024;
expect(agentService.isPortrait()).toBeTruthy();
expect(agentService.isLandscape()).toBeFalsy();
});
it("detects touch support", function () {
testWindow.ontouchstart = null;
expect(new AgentService(testWindow).isTouch())
.toBe(true);
delete testWindow.ontouchstart;
expect(new AgentService(testWindow).isTouch())
.toBe(false);
});
it("allows for checking browser type", function () {
testWindow.navigator.userAgent = "Chromezilla Safarifox";
agentService = new AgentService(testWindow);
expect(agentService.isBrowser("Chrome")).toBe(true);
expect(agentService.isBrowser("Firefox")).toBe(false);
});
});
}
);

View File

@@ -0,0 +1,109 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define(
["../src/DeviceClassifier", "../src/DeviceMatchers"],
function (DeviceClassifier, DeviceMatchers) {
var AGENT_SERVICE_METHODS = [
'isMobile',
'isPhone',
'isTablet',
'isPortrait',
'isLandscape',
'isTouch'
],
TEST_PERMUTATIONS = [
['isMobile', 'isPhone', 'isTouch', 'isPortrait'],
['isMobile', 'isPhone', 'isTouch', 'isLandscape'],
['isMobile', 'isTablet', 'isTouch', 'isPortrait'],
['isMobile', 'isTablet', 'isTouch', 'isLandscape'],
['isTouch'],
[]
];
describe("DeviceClassifier", function () {
var mockAgentService,
mockDocument,
mockBody;
beforeEach(function () {
mockAgentService = jasmine.createSpyObj(
'agentService',
AGENT_SERVICE_METHODS
);
mockDocument = jasmine.createSpyObj(
'$document',
['find']
);
mockBody = jasmine.createSpyObj(
'body',
['addClass']
);
mockDocument.find.and.callFake(function (sel) {
return sel === 'body' && mockBody;
});
AGENT_SERVICE_METHODS.forEach(function (m) {
mockAgentService[m].and.returnValue(false);
});
});
TEST_PERMUTATIONS.forEach(function (trueMethods) {
var summary = trueMethods.length === 0
? "device has no detected characteristics"
: "device " + (trueMethods.join(", "));
describe("when " + summary, function () {
var classifier; // eslint-disable-line
beforeEach(function () {
trueMethods.forEach(function (m) {
mockAgentService[m].and.returnValue(true);
});
classifier = new DeviceClassifier(
mockAgentService,
mockDocument
);
});
it("adds classes for matching, detected characteristics", function () {
Object.keys(DeviceMatchers).filter(function (m) {
return DeviceMatchers[m](mockAgentService);
}).forEach(function (key) {
expect(mockBody.addClass)
.toHaveBeenCalledWith(key);
});
});
it("does not add classes for non-matching characteristics", function () {
Object.keys(DeviceMatchers).filter(function (m) {
return !DeviceMatchers[m](mockAgentService);
}).forEach(function (key) {
expect(mockBody.addClass)
.not.toHaveBeenCalledWith(key);
});
});
});
});
});
}
);

View File

@@ -0,0 +1,78 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define(
["../src/DeviceMatchers"],
function (DeviceMatchers) {
describe("DeviceMatchers", function () {
var mockAgentService;
beforeEach(function () {
mockAgentService = jasmine.createSpyObj(
'agentService',
[
'isMobile',
'isPhone',
'isTablet',
'isPortrait',
'isLandscape',
'isTouch'
]
);
});
it("detects when a device is a desktop device", function () {
mockAgentService.isMobile.and.returnValue(false);
expect(DeviceMatchers.desktop(mockAgentService))
.toBe(true);
mockAgentService.isMobile.and.returnValue(true);
expect(DeviceMatchers.desktop(mockAgentService))
.toBe(false);
});
function method(deviceType) {
return "is" + deviceType[0].toUpperCase() + deviceType.slice(1);
}
[
"mobile",
"phone",
"tablet",
"landscape",
"portrait",
"landscape",
"touch"
].forEach(function (deviceType) {
it("detects when a device is a " + deviceType + " device", function () {
mockAgentService[method(deviceType)].and.returnValue(true);
expect(DeviceMatchers[deviceType](mockAgentService))
.toBe(true);
mockAgentService[method(deviceType)].and.returnValue(false);
expect(DeviceMatchers[deviceType](mockAgentService))
.toBe(false);
});
});
});
}
);

View File

@@ -0,0 +1,168 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define(
['../src/MCTDevice'],
function (MCTDevice) {
var JQLITE_METHODS = ['replaceWith'];
describe("The mct-device directive", function () {
var mockAgentService,
mockTransclude,
mockElement,
mockClone,
testAttrs,
directive;
function link() {
directive.link(null, mockElement, testAttrs, null, mockTransclude);
}
beforeEach(function () {
mockAgentService = jasmine.createSpyObj(
"agentService",
["isMobile", "isPhone", "isTablet", "isPortrait", "isLandscape"]
);
mockTransclude = jasmine.createSpy("$transclude");
mockElement = jasmine.createSpyObj(name, JQLITE_METHODS);
mockClone = jasmine.createSpyObj(name, JQLITE_METHODS);
mockTransclude.and.callFake(function (fn) {
fn(mockClone);
});
// Look desktop-like by default
mockAgentService.isLandscape.and.returnValue(true);
testAttrs = {};
directive = new MCTDevice(mockAgentService);
});
function expectInclusion() {
expect(mockElement.replaceWith)
.toHaveBeenCalledWith(mockClone);
}
function expectExclusion() {
expect(mockElement.replaceWith).not.toHaveBeenCalled();
}
it("is applicable at the attribute level", function () {
expect(directive.restrict).toEqual("A");
});
it("transcludes at the element level", function () {
expect(directive.transclude).toEqual('element');
});
it("has a greater priority number than ng-if", function () {
expect(directive.priority > 600).toBeTruthy();
});
it("restricts element inclusion for mobile devices", function () {
testAttrs.mctDevice = "mobile";
link();
expectExclusion();
mockAgentService.isMobile.and.returnValue(true);
link();
expectInclusion();
});
it("restricts element inclusion for tablet devices", function () {
testAttrs.mctDevice = "tablet";
mockAgentService.isMobile.and.returnValue(true);
link();
expectExclusion();
mockAgentService.isTablet.and.returnValue(true);
link();
expectInclusion();
});
it("restricts element inclusion for phone devices", function () {
testAttrs.mctDevice = "phone";
mockAgentService.isMobile.and.returnValue(true);
link();
expectExclusion();
mockAgentService.isPhone.and.returnValue(true);
link();
expectInclusion();
});
it("restricts element inclusion for desktop devices", function () {
testAttrs.mctDevice = "desktop";
mockAgentService.isMobile.and.returnValue(true);
link();
expectExclusion();
mockAgentService.isMobile.and.returnValue(false);
link();
expectInclusion();
});
it("restricts element inclusion for portrait orientation", function () {
testAttrs.mctDevice = "portrait";
link();
expectExclusion();
mockAgentService.isPortrait.and.returnValue(true);
link();
expectInclusion();
});
it("restricts element inclusion for landscape orientation", function () {
testAttrs.mctDevice = "landscape";
mockAgentService.isLandscape.and.returnValue(false);
mockAgentService.isPortrait.and.returnValue(true);
link();
expectExclusion();
mockAgentService.isLandscape.and.returnValue(true);
link();
expectInclusion();
});
it("allows multiple device characteristics to be requested", function () {
// Won't try to test every permutation here, just
// make sure the multi-characteristic feature has support.
testAttrs.mctDevice = "portrait mobile";
link();
// Neither portrait nor mobile, not called
expectExclusion();
mockAgentService.isPortrait.and.returnValue(true);
link();
// Was portrait, but not mobile, so no
expectExclusion();
mockAgentService.isMobile.and.returnValue(true);
link();
expectInclusion();
});
});
}
);

View File

@@ -379,7 +379,7 @@ define([
{
"name": "Math.uuid.js",
"version": "1.4.7",
"description": "Unique identifier generation (code adapted.)",
"description": "Unique identifer generation (code adapted.)",
"author": "Robert Kieffer",
"website": "https://github.com/broofa/node-uuid",
"copyright": "Copyright (c) 2010-2012 Robert Kieffer",

View File

@@ -30,8 +30,8 @@ define([
return function ImportExportPlugin() {
return function (openmct) {
ExportAsJSONAction.prototype.appliesTo = function (context) {
return this.openmct.$injector.get('policyService')
ExportAsJSONAction.appliesTo = function (context) {
return openmct.$injector.get('policyService')
.allow("creation", context.domainObject.getCapability("type")
);
};

View File

@@ -29,7 +29,7 @@ define(
],
function (ExportAsJSONAction, domainObjectFactory, MCT, AdapterCapability) {
describe("The export JSON action", function () {
xdescribe("The export JSON action", function () {
var context,
action,
@@ -102,7 +102,7 @@ define(
expect(action).toBeDefined();
});
xit("doesn't export non-creatable objects in tree", function () {
it("doesn't export non-creatable objects in tree", function () {
var nonCreatableType = {
hasFeature:
function (feature) {
@@ -149,7 +149,7 @@ define(
});
});
xit("can export self-containing objects", function () {
it("can export self-containing objects", function () {
var parent = domainObjectFactory({
name: 'parent',
model: {
@@ -191,7 +191,7 @@ define(
});
});
xit("exports links to external objects as new objects", function () {
it("exports links to external objects as new objects", function () {
var parent = domainObjectFactory({
name: 'parent',
model: {

View File

@@ -27,7 +27,7 @@ define(
],
function (ImportAsJSONAction, domainObjectFactory) {
describe("The import JSON action", function () {
xdescribe("The import JSON action", function () {
var context = {};
var action,
@@ -146,7 +146,7 @@ define(
});
});
xit("can import self-containing objects", function () {
it("can import self-containing objects", function () {
var compDomainObject = domainObjectFactory({
name: 'compObject',
model: { name: 'compObject'},
@@ -198,7 +198,7 @@ define(
});
});
xit("assigns new ids to each imported object", function () {
it("assigns new ids to each imported object", function () {
dialogService.getUserInput.and.returnValue(Promise.resolve(
{
selectFile: {

View File

@@ -47,7 +47,7 @@ define(
* @param $interval Angular's $interval service
* @param {string} space the name of the persistence space being served
* @param {string} root the root of the path to ElasticSearch
* @param {string} path the path to domain objects within ElasticSearch
* @param {stirng} path the path to domain objects within ElasticSearch
*/
function ElasticPersistenceProvider($http, $q, space, root, path) {
this.spaces = [space];

View File

@@ -287,7 +287,6 @@ define([
this.install(this.plugins.ViewLargeAction());
this.install(this.plugins.ObjectInterceptors());
this.install(this.plugins.NonEditableFolder());
this.install(this.plugins.DeviceClassifier());
}
MCT.prototype = Object.create(EventEmitter.prototype);

View File

@@ -60,7 +60,9 @@ class ActionsAPI extends EventEmitter {
}
_getCachedActionCollection(objectPath, view) {
return this._actionCollections.get(view);
let cachedActionCollection = this._actionCollections.get(view);
return cachedActionCollection;
}
_newActionCollection(objectPath, view, skipEnvironmentObservers) {

View File

@@ -42,7 +42,7 @@ import EventEmitter from 'EventEmitter';
*
* @typedef {object} NotificationModel
* @property {string} message The message to be displayed by the notification
* @property {number | 'unknown'} [progress] The progress of some ongoing task. Should be a number between 0 and 100, or
* @property {number | 'unknown'} [progress] The progres of some ongoing task. Should be a number between 0 and 100, or
* with the string literal 'unknown'.
* @property {string} [progressText] A message conveying progress of some ongoing task.
@@ -98,7 +98,7 @@ export default class NotificationAPI extends EventEmitter {
* Present an alert to the user.
* @param {string} message The message to display to the user.
* @param {Object} [options] object with following properties
* autoDismissTimeout: {number} in milliseconds to automatically dismisses notification
* autoDismissTimeout: {number} in miliseconds to automatically dismisses notification
* link: {Object} Add a link to notifications for navigation
* onClick: callback function
* cssClass: css class name to add style on link
@@ -119,7 +119,7 @@ export default class NotificationAPI extends EventEmitter {
* Present an error message to the user
* @param {string} message
* @param {Object} [options] object with following properties
* autoDismissTimeout: {number} in milliseconds to automatically dismisses notification
* autoDismissTimeout: {number} in miliseconds to automatically dismisses notification
* link: {Object} Add a link to notifications for navigation
* onClick: callback function
* cssClass: css class name to add style on link

View File

@@ -358,20 +358,6 @@ ObjectAPI.prototype.applyGetInterceptors = function (identifier, domainObject) {
return domainObject;
};
/**
* Return relative url path from a given object path
* eg: #/browse/mine/cb56f6bf-c900-43b7-b923-2e3b64b412db/6e89e858-77ce-46e4-a1ad-749240286497/....
* @param {Array} objectPath
* @returns {string} relative url for object
*/
ObjectAPI.prototype.getRelativePath = function (objectPath) {
return objectPath
.map(p => this.makeKeyString(p.identifier))
.reverse()
.join('/')
;
};
/**
* Modify a domain object.
* @param {module:openmct.DomainObject} object the object to mutate

View File

@@ -10,37 +10,28 @@ const cssClasses = {
};
class Overlay extends EventEmitter {
constructor({
buttons,
autoHide = true,
dismissable = true,
element,
onDestroy,
size
} = {}) {
constructor(options) {
super();
this.dismissable = options.dismissable !== false;
this.container = document.createElement('div');
this.container.classList.add('l-overlay-wrapper', cssClasses[size]);
this.autoHide = autoHide;
this.dismissable = dismissable !== false;
this.container.classList.add('l-overlay-wrapper', cssClasses[options.size]);
this.component = new Vue({
components: {
OverlayComponent: OverlayComponent
},
provide: {
dismiss: this.dismiss.bind(this),
element,
buttons,
element: options.element,
buttons: options.buttons,
dismissable: this.dismissable
},
components: {
OverlayComponent: OverlayComponent
},
template: '<overlay-component></overlay-component>'
});
if (onDestroy) {
this.once('destroy', onDestroy);
if (options.onDestroy) {
this.once('destroy', options.onDestroy);
}
}

View File

@@ -30,10 +30,7 @@ class OverlayAPI {
*/
showOverlay(overlay) {
if (this.activeOverlays.length) {
const previousOverlay = this.activeOverlays[this.activeOverlays.length - 1];
if (previousOverlay.autoHide) {
previousOverlay.container.classList.add('invisible');
}
this.activeOverlays[this.activeOverlays.length - 1].container.classList.add('invisible');
}
this.activeOverlays.push(overlay);
@@ -63,7 +60,7 @@ class OverlayAPI {
* A description of option properties that can be passed into the overlay
* @typedef options
* @property {object} element DOMElement that is to be inserted/shown on the overlay
* @property {string} size preferred size of the overlay (large, small, fit)
* @property {string} size prefered size of the overlay (large, small, fit)
* @property {array} buttons optional button objects with label and callback properties
* @property {function} onDestroy callback to be called when overlay is destroyed
* @property {boolean} dismissable allow user to dismiss overlay by using esc, and clicking away

View File

@@ -12,7 +12,7 @@
></button>
<div
ref="element"
class="c-overlay__contents js-notebook-snapshot-item-wrapper"
class="c-overlay__contents"
tabindex="0"
></div>
<div

View File

@@ -281,7 +281,7 @@ define([
* (start, end, etc.), sort order, and strategies for retrieving
* telemetry (aggregation, latest available, etc.).
*
* @method requestCollection
* @method requestTelemetryCollection
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
* @param {module:openmct.DomainObject} domainObject the object
* which has associated telemetry
@@ -289,7 +289,7 @@ define([
* options for this telemetry collection request
* @returns {TelemetryCollection} a TelemetryCollection instance
*/
TelemetryAPI.prototype.requestCollection = function (domainObject, options = {}) {
TelemetryAPI.prototype.requestTelemetryCollection = function (domainObject, options = {}) {
return new TelemetryCollection(
this.openmct,
domainObject,

View File

@@ -603,7 +603,7 @@ describe('Telemetry API', function () {
});
it('when requested, returns an instance of telemetry collection', () => {
const telemetryCollection = telemetryAPI.requestCollection(domainObject);
const telemetryCollection = telemetryAPI.requestTelemetryCollection(domainObject);
expect(telemetryCollection).toBeInstanceOf(TelemetryCollection);
});

View File

@@ -23,11 +23,6 @@
import _ from 'lodash';
import EventEmitter from 'EventEmitter';
const ERRORS = {
TIMESYSTEM_KEY: 'All telemetry metadata must have a telemetry value with a key that matches the key of the active time system.',
LOADED: 'Telemetry Collection has already been loaded.'
};
/** Class representing a Telemetry Collection. */
export class TelemetryCollection extends EventEmitter {
@@ -62,7 +57,7 @@ export class TelemetryCollection extends EventEmitter {
*/
load() {
if (this.loaded) {
this._error(ERRORS.LOADED);
throw new Error('Telemetry Collection has already been loaded.');
}
this._timeSystem(this.openmct.time.timeSystem());
@@ -128,13 +123,13 @@ export class TelemetryCollection extends EventEmitter {
try {
this.requestAbort = new AbortController();
this.options.signal = this.requestAbort.signal;
this.options.abortSignal = this.requestAbort.signal;
historicalData = await this.historicalProvider.request(this.domainObject, this.options);
this.requestAbort = undefined;
} catch (error) {
console.error('Error requesting telemetry data...');
this.requestAbort = undefined;
this._error(error);
throw new Error(error);
}
this._processNewTelemetry(historicalData);
@@ -194,7 +189,7 @@ export class TelemetryCollection extends EventEmitter {
if (endIndex > startIndex) {
let potentialDupes = this.boundedTelemetry.slice(startIndex, endIndex);
isDuplicate = potentialDupes.some(_.isEqual.bind(undefined, datum));
isDuplicate = potentialDupes.some(_.isEqual(undefined, datum));
}
}
@@ -312,16 +307,8 @@ export class TelemetryCollection extends EventEmitter {
* @private
*/
_timeSystem(timeSystem) {
let domains = this.metadata.valuesForHints(['domain']);
let domain = domains.find((d) => d.key === timeSystem.key);
if (domain === undefined) {
this._error(ERRORS.TIMESYSTEM_KEY);
}
// timeKey is used to create a dummy datum used for sorting
this.timeKey = domain.source; // this defaults to key if no source is set
let metadataValue = this.metadata.value(timeSystem.key) || { format: timeSystem.key };
this.timeKey = timeSystem.key;
let metadataValue = this.metadata.value(this.timeKey) || { format: this.timeKey };
let valueFormatter = this.openmct.telemetry.getValueFormatter(metadataValue);
this.parseTime = (datum) => {
@@ -376,13 +363,4 @@ export class TelemetryCollection extends EventEmitter {
_unwatchTimeSystem() {
this.openmct.time.off('timeSystem', this._timeSystem, this);
}
/**
* will throw a new Error, for passed in message
* @param {string} message Message describing the error
* @private
*/
_error(message) {
throw new Error(message);
}
}

View File

@@ -90,7 +90,7 @@ class ImageExporter {
element.id = oldId;
},
removeContainer: true // Set to false to debug what html2canvas renders
}).then(canvas => {
}).then(function (canvas) {
dialog.dismiss();
return new Promise(function (resolve, reject) {
@@ -105,10 +105,9 @@ class ImageExporter {
return canvas.toBlob(blob => resolve({ blob }), mimeType);
});
}).catch(error => {
}, function (error) {
console.log('error capturing image', error);
dialog.dismiss();
console.error('error capturing image', error);
const errorDialog = overlays.dialog({
iconClass: 'error',
message: 'Image was not captured successfully!',

View File

@@ -1,72 +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.
*****************************************************************************/
/**
* Runs at application startup and adds a subset of the following
* CSS classes to the body of the document, depending on device
* attributes:
*
* * `mobile`: Phones or tablets.
* * `phone`: Phones specifically.
* * `tablet`: Tablets specifically.
* * `desktop`: Non-mobile devices.
* * `portrait`: Devices in a portrait-style orientation.
* * `landscape`: Devices in a landscape-style orientation.
* * `touch`: Device supports touch events.
*
* @param {utils/agent/Agent} agent
* the service used to examine the user agent
* @param document the HTML DOM document object
* @constructor
*/
import DeviceMatchers from "./DeviceMatchers";
export default (agent, document) => {
const body = document.body;
Object.keys(DeviceMatchers).forEach((key, index, array) => {
if (DeviceMatchers[key](agent)) {
body.classList.add(key);
}
});
if (agent.isMobile()) {
const mediaQuery = window.matchMedia("(orientation: landscape)");
function eventHandler(event) {
console.log("changed");
if (event.matches) {
body.classList.remove("portrait");
body.classList.add("landscape");
} else {
body.classList.remove("landscape");
body.classList.add("portrait");
}
}
if (mediaQuery.addEventListener) {
mediaQuery.addEventListener(`change`, eventHandler);
} else {
// Deprecated 'MediaQueryList' API, <Safari 14, IE, <Edge 16
mediaQuery.addListener(eventHandler);
}
}
};

View File

@@ -1,105 +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 DeviceClassifier from "./DeviceClassifier";
import DeviceMatchers from "./DeviceMatchers";
const AGENT_METHODS = [
"isMobile",
"isPhone",
"isTablet",
"isPortrait",
"isLandscape",
"isTouch"
];
const TEST_PERMUTATIONS = [
["isMobile", "isPhone", "isTouch", "isPortrait"],
["isMobile", "isPhone", "isTouch", "isLandscape"],
["isMobile", "isTablet", "isTouch", "isPortrait"],
["isMobile", "isTablet", "isTouch", "isLandscape"],
["isTouch"],
[]
];
describe("DeviceClassifier", function () {
let mockAgent;
let mockDocument;
let mockClassList;
beforeEach(function () {
mockAgent = jasmine.createSpyObj(
"agent",
AGENT_METHODS
);
mockClassList = jasmine.createSpyObj("classList", ["add"]);
mockDocument = jasmine.createSpyObj(
"document",
{},
{ body: { classList: mockClassList } }
);
AGENT_METHODS.forEach(function (m) {
mockAgent[m].and.returnValue(false);
});
});
TEST_PERMUTATIONS.forEach(function (trueMethods) {
const summary =
trueMethods.length === 0
? "device has no detected characteristics"
: "device " + trueMethods.join(", ");
describe("when " + summary, function () {
beforeEach(function () {
trueMethods.forEach(function (m) {
mockAgent[m].and.returnValue(true);
});
// eslint-disable-next-line no-new
DeviceClassifier(mockAgent, mockDocument);
});
it("adds classes for matching, detected characteristics", function () {
Object.keys(DeviceMatchers)
.filter(function (m) {
return DeviceMatchers[m](mockAgent);
})
.forEach(function (key) {
expect(mockDocument.body.classList.add).toHaveBeenCalledWith(key);
});
});
it("does not add classes for non-matching characteristics", function () {
Object.keys(DeviceMatchers)
.filter(function (m) {
return !DeviceMatchers[m](mockAgent);
})
.forEach(function (key) {
expect(mockDocument.body.classList.add).not.toHaveBeenCalledWith(
key
);
});
});
});
});
});

View File

@@ -1,65 +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 DeviceMatchers from "./DeviceMatchers";
describe("DeviceMatchers", function () {
let mockAgent;
beforeEach(function () {
mockAgent = jasmine.createSpyObj("agent", [
"isMobile",
"isPhone",
"isTablet",
"isPortrait",
"isLandscape",
"isTouch"
]);
});
it("detects when a device is a desktop device", function () {
mockAgent.isMobile.and.returnValue(false);
expect(DeviceMatchers.desktop(mockAgent)).toBe(true);
mockAgent.isMobile.and.returnValue(true);
expect(DeviceMatchers.desktop(mockAgent)).toBe(false);
});
function method(deviceType) {
return "is" + deviceType[0].toUpperCase() + deviceType.slice(1);
}
[
"mobile",
"phone",
"tablet",
"landscape",
"portrait",
"landscape",
"touch"
].forEach(function (deviceType) {
it("detects when a device is a " + deviceType + " device", function () {
mockAgent[method(deviceType)].and.returnValue(true);
expect(DeviceMatchers[deviceType](mockAgent)).toBe(true);
mockAgent[method(deviceType)].and.returnValue(false);
expect(DeviceMatchers[deviceType](mockAgent)).toBe(false);
});
});
});

View File

@@ -20,18 +20,6 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
function inSelectionPath(openmct, domainObject) {
const domainObjectIdentifier = domainObject.identifier;
return openmct.selection.get().some(selectionPath => {
return selectionPath.some(objectInPath => {
const objectInPathIdentifier = objectInPath.context.item.identifier;
return openmct.objects.areIdsEqual(objectInPathIdentifier, domainObjectIdentifier);
});
});
}
export default class ClearDataAction {
constructor(openmct, appliesToObjects) {
this.name = 'Clear Data for Object';
@@ -43,36 +31,11 @@ export default class ClearDataAction {
this._appliesToObjects = appliesToObjects;
}
invoke(objectPath) {
let domainObject = null;
if (objectPath) {
domainObject = objectPath[0];
}
this._openmct.objectViews.emit('clearData', domainObject);
this._openmct.objectViews.emit('clearData', objectPath[0]);
}
appliesTo(objectPath) {
if (!objectPath) {
return false;
}
let contextualDomainObject = objectPath[0];
const contextualDomainObject = objectPath[0];
// first check to see if this action applies to this sort of object at all
const appliesToThisObject = this._appliesToObjects.some(type => {
return contextualDomainObject.type === type;
});
if (!appliesToThisObject) {
// we've selected something not applicable
return false;
}
const objectInSelectionPath = inSelectionPath(this._openmct, contextualDomainObject);
if (objectInSelectionPath) {
return true;
} else {
// if this it doesn't match up, check to see if we're in a composition (i.e., layout)
const routerPath = this._openmct.router.path[0];
return routerPath.type === 'layout';
}
return this._appliesToObjects.filter(type => contextualDomainObject.type === type).length;
}
}

View File

@@ -22,7 +22,7 @@
define([
'./components/globalClearIndicator.vue',
'./ClearDataAction',
'./clearDataAction',
'vue'
], function (
GlobaClearIndicator,

View File

@@ -1,140 +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 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,
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([]));
expect(mockIndicatorProvider.add).toHaveBeenCalled();
});
it('Clear Data context menu action is installed', () => {
openmct.install(ClearDataActionPlugin([]));
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);
});
});

View File

@@ -0,0 +1,64 @@
/*****************************************************************************
* 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,', function () {
const mockObjectViews = jasmine.createSpyObj('objectViews', ['emit']);
const mockIndicatorProvider = jasmine.createSpyObj('indicators', ['add']);
const mockActionsProvider = jasmine.createSpyObj('actions', ['register']);
const openmct = {
objectViews: mockObjectViews,
indicators: mockIndicatorProvider,
actions: mockActionsProvider,
install: function (plugin) {
plugin(this);
}
};
const mockObjectPath = [
{name: 'mockObject1'},
{name: 'mockObject2'}
];
it('Global Clear Indicator is installed', function () {
openmct.install(ClearDataActionPlugin([]));
expect(mockIndicatorProvider.add).toHaveBeenCalled();
});
it('Clear Data context menu action is installed', function () {
openmct.install(ClearDataActionPlugin([]));
expect(mockActionsProvider.register).toHaveBeenCalled();
});
it('clear data action emits a clearData event when invoked', function () {
let action = new ClearDataAction(openmct);
action.invoke(mockObjectPath);
expect(mockObjectViews.emit).toHaveBeenCalledWith('clearData', mockObjectPath[0]);
});
});

View File

@@ -273,7 +273,10 @@ export default {
this.openmct.objects.getOriginalPath(this.conditionSetDomainObject.identifier).then(
(objectPath) => {
this.objectPath = objectPath;
this.navigateToPath = '#/browse/' + this.openmct.objects.getRelativePath(this.objectPath);
this.navigateToPath = '#/browse/' + this.objectPath
.map(o => o && this.openmct.objects.makeKeyString(o.identifier))
.reverse()
.join('/');
}
);
},

View File

@@ -141,7 +141,6 @@ const NON_STYLEABLE_CONTAINER_TYPES = [
const NON_STYLEABLE_LAYOUT_ITEM_TYPES = [
'line-view',
'box-view',
'ellipse-view',
'image-view'
];
@@ -297,7 +296,10 @@ export default {
this.openmct.objects.getOriginalPath(this.conditionSetDomainObject.identifier).then(
(objectPath) => {
this.objectPath = objectPath;
this.navigateToPath = '#/browse/' + this.openmct.objects.getRelativePath(this.objectPath);
this.navigateToPath = '#/browse/' + this.objectPath
.map(o => o && this.openmct.objects.makeKeyString(o.identifier))
.reverse()
.join('/');
}
);
},
@@ -319,7 +321,7 @@ export default {
if (item) {
const type = this.openmct.types.get(item.type);
if (type && type.definition) {
creatable = (type.definition.creatable !== undefined && (type.definition.creatable === 'true' || type.definition.creatable === true));
creatable = (type.definition.creatable === true);
}
}

View File

@@ -230,7 +230,7 @@ describe('the plugin', function () {
};
const staticStyle = {
"style": {
"backgroundColor": "#666666",
"backgroundColor": "#717171",
"border": "1px solid #00ffff"
}
};
@@ -238,7 +238,7 @@ describe('the plugin', function () {
"conditionId": "39584410-cbf9-499e-96dc-76f27e69885d",
"style": {
"isStyleInvisible": "",
"backgroundColor": "#666666",
"backgroundColor": "#717171",
"border": "1px solid #ffff00"
}
};
@@ -250,7 +250,7 @@ describe('the plugin', function () {
"configuration": {
"items": [
{
"fill": "#666666",
"fill": "#717171",
"stroke": "",
"x": 1,
"y": 1,
@@ -259,22 +259,12 @@ describe('the plugin', function () {
"type": "box-view",
"id": "89b88746-d325-487b-aec4-11b79afff9e8"
},
{
"fill": "#666666",
"stroke": "",
"x": 1,
"y": 1,
"width": 10,
"height": 5,
"type": "ellipse-view",
"id": "19b88746-d325-487b-aec4-11b79afff9z8"
},
{
"x": 18,
"y": 9,
"x2": 23,
"y2": 4,
"stroke": "#666666",
"stroke": "#717171",
"type": "line-view",
"id": "57d49a28-7863-43bd-9593-6570758916f0"
},
@@ -309,12 +299,12 @@ describe('the plugin', function () {
"y": 9,
"x2": 23,
"y2": 4,
"stroke": "#666666",
"stroke": "#717171",
"type": "line-view",
"id": "57d49a28-7863-43bd-9593-6570758916f0"
};
boxLayoutItem = {
"fill": "#666666",
"fill": "#717171",
"stroke": "",
"x": 1,
"y": 1,

View File

@@ -29,10 +29,9 @@ const styleProps = {
noneValue: NONE_VALUE,
applicableForType: type => {
return !type ? true : (type === 'text-view'
|| type === 'telemetry-view'
|| type === 'box-view'
|| type === 'ellipse-view'
|| type === 'subobject-view');
|| type === 'telemetry-view'
|| type === 'box-view'
|| type === 'subobject-view');
}
},
border: {
@@ -42,7 +41,6 @@ const styleProps = {
return !type ? true : (type === 'text-view'
|| type === 'telemetry-view'
|| type === 'box-view'
|| type === 'ellipse-view'
|| type === 'image-view'
|| type === 'line-view'
|| type === 'subobject-view');

View File

@@ -149,7 +149,6 @@ define(['lodash'], function (_) {
return type === 'text-view'
|| type === 'telemetry-view'
|| type === 'box-view'
|| type === 'ellipse-view'
|| type === 'image-view'
|| type === 'line-view'
|| type === 'subobject-view';
@@ -181,10 +180,6 @@ define(['lodash'], function (_) {
"name": "Box",
"class": "icon-box-round-corners"
},
{
"name": "Ellipse",
"class": "icon-circle"
},
{
"name": "Line",
"class": "icon-line-horz"
@@ -750,7 +745,7 @@ define(['lodash'], function (_) {
if (toolbar.remove.length === 0) {
toolbar.remove = [getRemoveButton(selectedParent, selectionPath, selectedObjects)];
}
} else if (layoutItem.type === 'box-view' || layoutItem.type === 'ellipse-view') {
} else if (layoutItem.type === 'box-view') {
if (toolbar.position.length === 0) {
toolbar.position = [
getStackOrder(selectedParent, selectionPath),

View File

@@ -43,7 +43,7 @@ import conditionalStylesMixin from '../mixins/objectStyles-mixin';
export default {
makeDefinition() {
return {
fill: '#666666',
fill: '#717171',
stroke: '',
x: 1,
y: 1,

View File

@@ -76,7 +76,6 @@ import uuid from 'uuid';
import SubobjectView from './SubobjectView.vue';
import TelemetryView from './TelemetryView.vue';
import BoxView from './BoxView.vue';
import EllipseView from './EllipseView.vue';
import TextView from './TextView.vue';
import LineView from './LineView.vue';
import ImageView from './ImageView.vue';
@@ -113,7 +112,6 @@ const ITEM_TYPE_VIEW_MAP = {
'subobject-view': SubobjectView,
'telemetry-view': TelemetryView,
'box-view': BoxView,
'ellipse-view': EllipseView,
'line-view': LineView,
'text-view': TextView,
'image-view': ImageView

View File

@@ -28,19 +28,19 @@
>
<div
class="c-frame-edit__handle c-frame-edit__handle--nw"
@mousedown.left="startResize([1,1], [-1,-1], $event)"
@mousedown="startResize([1,1], [-1,-1], $event)"
></div>
<div
class="c-frame-edit__handle c-frame-edit__handle--ne"
@mousedown.left="startResize([0,1], [1,-1], $event)"
@mousedown="startResize([0,1], [1,-1], $event)"
></div>
<div
class="c-frame-edit__handle c-frame-edit__handle--sw"
@mousedown.left="startResize([1,0], [-1,1], $event)"
@mousedown="startResize([1,0], [-1,1], $event)"
></div>
<div
class="c-frame-edit__handle c-frame-edit__handle--se"
@mousedown.left="startResize([0,0], [1,1], $event)"
@mousedown="startResize([0,0], [1,1], $event)"
></div>
</div>
</template>

View File

@@ -1,122 +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.
*****************************************************************************/
<template>
<layout-frame
:item="item"
:grid-size="gridSize"
:is-editing="isEditing"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')"
>
<div
class="c-ellipse-view u-style-receiver js-style-receiver"
:class="[styleClass]"
:style="style"
></div>
</layout-frame>
</template>
<script>
import LayoutFrame from './LayoutFrame.vue';
import conditionalStylesMixin from '../mixins/objectStyles-mixin';
export default {
makeDefinition() {
return {
fill: '#666666',
stroke: '',
x: 1,
y: 1,
width: 10,
height: 10
};
},
components: {
LayoutFrame
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
index: {
type: Number,
required: true
},
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
},
computed: {
style() {
if (this.itemStyle) {
return this.itemStyle;
} else {
return {
backgroundColor: this.item.fill,
border: this.item.stroke ? '1px solid ' + this.item.stroke : ''
};
}
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el, this.context, this.initSelect);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
}
};
</script>

View File

@@ -33,7 +33,7 @@
<slot></slot>
<div
class="c-frame__move-bar"
@mousedown.left="startMove($event)"
@mousedown="isEditing ? startMove([1,1], [0,0], $event) : null"
></div>
</div>
</template>
@@ -93,11 +93,7 @@ export default {
return value - this.initialPosition[index];
}.bind(this));
},
startMove(event, posFactor = [1, 1], dimFactor = [0, 0]) {
if (!this.isEditing) {
return;
}
startMove(posFactor, dimFactor, event) {
document.body.addEventListener('mousemove', this.continueMove);
document.body.addEventListener('mouseup', this.endMove);
this.dragPosition = {

View File

@@ -45,7 +45,7 @@
<div
class="c-frame__move-bar"
@mousedown.left="startDrag($event)"
@mousedown="startDrag($event)"
></div>
<div
v-if="showFrameEdit"
@@ -96,7 +96,7 @@ export default {
y: 10,
x2: 10,
y2: 5,
stroke: '#666666'
stroke: '#717171'
};
},
mixins: [conditionalStylesMixin],

View File

@@ -1,5 +1,4 @@
.c-box-view,
.c-ellipse-view {
.c-box-view {
border-width: $drawingObjBorderW !important;
display: flex;
align-items: stretch;
@@ -9,10 +8,6 @@
}
}
.c-ellipse-view {
border-radius: 50%;
}
.c-line-view {
&.c-frame {
box-shadow: none !important;

View File

@@ -186,7 +186,7 @@ describe('the plugin', function () {
'configuration': {
'items': [
{
'fill': '#666666',
'fill': '#717171',
'stroke': '',
'x': 1,
'y': 1,
@@ -195,22 +195,12 @@ describe('the plugin', function () {
'type': 'box-view',
'id': '89b88746-d325-487b-aec4-11b79afff9e8'
},
{
'fill': '#666666',
'stroke': '',
'x': 1,
'y': 1,
'width': 10,
'height': 10,
'type': 'ellipse-view',
'id': '19b88746-d325-487b-aec4-11b79afff9z8'
},
{
'x': 18,
'y': 9,
'x2': 23,
'y2': 4,
'stroke': '#666666',
'stroke': '#717171',
'type': 'line-view',
'id': '57d49a28-7863-43bd-9593-6570758916f0'
},
@@ -351,7 +341,7 @@ describe('the plugin', function () {
it('provides controls including separators', () => {
const displayLayoutToolbar = openmct.toolbars.get(selection);
expect(displayLayoutToolbar.length).toBe(7);
expect(displayLayoutToolbar.length).toBe(9);
});
});
});

View File

@@ -140,7 +140,6 @@ import SearchResults from './SearchResults.vue';
import Sidebar from './Sidebar.vue';
import { clearDefaultNotebook, getDefaultNotebook, setDefaultNotebook, setDefaultNotebookSectionId, setDefaultNotebookPageId } from '../utils/notebook-storage';
import { addNotebookEntry, createNewEmbed, getEntryPosById, getNotebookEntries, mutateObject } from '../utils/notebook-entries';
import { saveNotebookImageDomainObject, updateNamespaceOfDomainObject } from '../utils/notebook-image';
import { NOTEBOOK_VIEW_TYPE } from '../notebook-constants';
import objectUtils from 'objectUtils';
@@ -386,13 +385,9 @@ export default {
const snapshotId = event.dataTransfer.getData('openmct/snapshot/id');
if (snapshotId.length) {
const snapshot = this.snapshotContainer.getSnapshot(snapshotId);
this.newEntry(snapshot.embedObject);
this.newEntry(snapshot);
this.snapshotContainer.removeSnapshot(snapshotId);
const namespace = this.domainObject.identifier.namespace;
const notebookImageDomainObject = updateNamespaceOfDomainObject(snapshot.notebookImageDomainObject, namespace);
saveNotebookImageDomainObject(this.openmct, notebookImageDomainObject);
return;
}
@@ -456,9 +451,12 @@ export default {
: undefined;
},
getDefaultNotebookObject() {
const defaultNotebook = getDefaultNotebook();
const oldNotebookStorage = getDefaultNotebook();
if (!oldNotebookStorage) {
return null;
}
return defaultNotebook && this.openmct.objects.get(defaultNotebook.identifier);
return this.openmct.objects.get(oldNotebookStorage.identifier);
},
getLinktoNotebook() {
const objectPath = this.openmct.router.path;

View File

@@ -40,7 +40,7 @@ export default {
components: {
PopupMenu
},
inject: ['openmct', 'snapshotContainer'],
inject: ['openmct'],
props: {
embed: {
type: Object,
@@ -48,12 +48,6 @@ export default {
return {};
}
},
isSnapshotContainer: {
type: Boolean,
default() {
return false;
}
},
removeActionString: {
type: String,
default() {
@@ -141,14 +135,6 @@ export default {
return;
}
if (this.isSnapshotContainer) {
const snapshot = this.snapshotContainer.getSnapshot(this.embed.id);
const fullSizeImageURL = snapshot.notebookImageDomainObject.configuration.fullSizeImageURL;
painterroInstance.show(fullSizeImageURL);
return;
}
this.openmct.objects.get(fullSizeImageObjectIdentifier)
.then(object => {
painterroInstance.show(object.configuration.fullSizeImageURL);
@@ -204,14 +190,6 @@ export default {
return;
}
if (this.isSnapshotContainer) {
const snapshot = this.snapshotContainer.getSnapshot(this.embed.id);
const fullSizeImageURL = snapshot.notebookImageDomainObject.configuration.fullSizeImageURL;
this.openSnapshotOverlay(fullSizeImageURL);
return;
}
this.openmct.objects.get(fullSizeImageObjectIdentifier)
.then(object => {
this.openSnapshotOverlay(object.configuration.fullSizeImageURL);
@@ -281,20 +259,8 @@ export default {
updateSnapshot(snapshotObject) {
this.embed.snapshot.thumbnailImage = snapshotObject.thumbnailImage;
this.updateNotebookImageDomainObjectSnapshot(snapshotObject);
updateNotebookImageDomainObject(this.openmct, this.embed.snapshot.fullSizeImageObjectIdentifier, snapshotObject.fullSizeImage);
this.updateEmbed(this.embed);
},
updateNotebookImageDomainObjectSnapshot(snapshotObject) {
if (this.isSnapshotContainer) {
const snapshot = this.snapshotContainer.getSnapshot(this.embed.id);
snapshot.embedObject.snapshot.thumbnailImage = snapshotObject.thumbnailImage;
snapshot.notebookImageDomainObject.configuration.fullSizeImageURL = snapshotObject.fullSizeImage.src;
this.snapshotContainer.updateSnapshot(snapshot);
} else {
updateNotebookImageDomainObject(this.openmct, this.embed.snapshot.fullSizeImageObjectIdentifier, snapshotObject.fullSizeImage);
}
}
}
};

View File

@@ -102,11 +102,9 @@
<script>
import NotebookEmbed from './NotebookEmbed.vue';
import TextHighlight from '../../../utils/textHighlight/TextHighlight.vue';
import { createNewEmbed } from '../utils/notebook-entries';
import { saveNotebookImageDomainObject, updateNamespaceOfDomainObject } from '../utils/notebook-image';
import Moment from 'moment';
import TextHighlight from '../../../utils/textHighlight/TextHighlight.vue';
export default {
components: {
@@ -212,12 +210,8 @@ export default {
const snapshotId = $event.dataTransfer.getData('openmct/snapshot/id');
if (snapshotId.length) {
const snapshot = this.snapshotContainer.getSnapshot(snapshotId);
this.entry.embeds.push(snapshot.embedObject);
this.snapshotContainer.removeSnapshot(snapshotId);
const namespace = this.domainObject.identifier.namespace;
const notebookImageDomainObject = updateNamespaceOfDomainObject(snapshot.notebookImageDomainObject, namespace);
saveNotebookImageDomainObject(this.openmct, notebookImageDomainObject);
this.entry.embeds.push(snapshot);
} else {
const data = $event.dataTransfer.getData('openmct/domain-object-path');
const objectPath = JSON.parse(data);

View File

@@ -17,26 +17,19 @@
<script>
import Snapshot from '../snapshot';
import { getDefaultNotebook, validateNotebookStorageObject } from '../utils/notebook-storage';
import { getDefaultNotebook, getNotebookSectionAndPage, validateNotebookStorageObject } from '../utils/notebook-storage';
import { NOTEBOOK_DEFAULT, NOTEBOOK_SNAPSHOT } from '../notebook-constants';
import { getMenuItems } from '../utils/notebook-snapshot-menu';
export default {
inject: ['openmct'],
props: {
currentView: {
type: Object,
default() {
return {};
}
},
domainObject: {
type: Object,
default() {
return {};
}
},
isPreview: {
ignoreLink: {
type: Boolean,
default() {
return false;
@@ -57,53 +50,66 @@ export default {
},
mounted() {
validateNotebookStorageObject();
this.getDefaultNotebookObject();
this.notebookSnapshot = new Snapshot(this.openmct);
this.setDefaultNotebookStatus();
},
methods: {
getPreviewObjectLink() {
const relativePath = this.openmct.objects.getRelativePath(this.objectPath);
const urlParams = this.openmct.router.getParams();
urlParams.view = this.currentView.key;
getDefaultNotebookObject() {
const defaultNotebook = getDefaultNotebook();
const urlParamsString = Object.entries(urlParams)
.map(([key, value]) => `${key}=${value}`)
.join('&');
return `#/browse/${relativePath}?${urlParamsString}`;
return defaultNotebook && this.openmct.objects.get(defaultNotebook.identifier);
},
async showMenu(event) {
const menuItemOptions = {
default: {
cssClass: 'icon-notebook',
name: `Save to Notebook`,
onItemClicked: () => this.snapshot(NOTEBOOK_DEFAULT, event.target)
},
snapshot: {
cssClass: 'icon-camera',
name: 'Save to Notebook Snapshots',
onItemClicked: () => this.snapshot(NOTEBOOK_SNAPSHOT, event.target)
}
};
const notebookTypes = await getMenuItems(this.openmct, menuItemOptions);
const notebookTypes = [];
const elementBoundingClientRect = this.$el.getBoundingClientRect();
const x = elementBoundingClientRect.x;
const y = elementBoundingClientRect.y + elementBoundingClientRect.height;
const defaultNotebookObject = await this.getDefaultNotebookObject();
if (defaultNotebookObject) {
const defaultNotebook = getDefaultNotebook();
const { section, page } = getNotebookSectionAndPage(defaultNotebookObject, defaultNotebook.defaultSectionId, defaultNotebook.defaultPageId);
if (section && page) {
const name = defaultNotebookObject.name;
const sectionName = section.name;
const pageName = page.name;
const defaultPath = `${name} - ${sectionName} - ${pageName}`;
notebookTypes.push({
cssClass: 'icon-notebook',
name: `Save to Notebook ${defaultPath}`,
onItemClicked: () => {
return this.snapshot(NOTEBOOK_DEFAULT);
}
});
}
}
notebookTypes.push({
cssClass: 'icon-camera',
name: 'Save to Notebook Snapshots',
onItemClicked: () => {
return this.snapshot(NOTEBOOK_SNAPSHOT);
}
});
this.openmct.menus.showMenu(x, y, notebookTypes);
},
snapshot(notebookType, target) {
snapshot(notebookType) {
this.$nextTick(() => {
const wrapper = target && target.closest('.js-notebook-snapshot-item-wrapper')
|| document;
const element = wrapper.querySelector('.js-notebook-snapshot-item');
const element = document.querySelector('.c-overlay__contents')
|| document.getElementsByClassName('l-shell__main-container')[0];
const bounds = this.openmct.time.bounds();
const link = !this.ignoreLink
? window.location.hash
: null;
const objectPath = this.objectPath || this.openmct.router.path;
const link = this.isPreview
? this.getPreviewObjectLink()
: window.location.hash;
const snapshotMeta = {
bounds: this.openmct.time.bounds(),
bounds,
link,
objectPath,
openmct: this.openmct

View File

@@ -27,15 +27,15 @@
</div><!-- closes l-browse-bar -->
<div class="c-snapshots">
<span v-for="snapshot in snapshots"
:key="snapshot.embedObject.id"
:key="snapshot.id"
draggable="true"
@dragstart="startEmbedDrag(snapshot, $event)"
>
<NotebookEmbed ref="notebookEmbed"
:key="snapshot.embedObject.id"
:embed="snapshot.embedObject"
:is-snapshot-container="true"
:key="snapshot.id"
:embed="snapshot"
:remove-action-string="'Delete Snapshot'"
@updateEmbed="updateSnapshot"
@removeEmbed="removeSnapshot"
/>
</span>
@@ -119,8 +119,11 @@ export default {
this.snapshots = this.snapshotContainer.getSnapshots();
},
startEmbedDrag(snapshot, event) {
event.dataTransfer.setData('text/plain', snapshot.embedObject.id);
event.dataTransfer.setData('openmct/snapshot/id', snapshot.embedObject.id);
event.dataTransfer.setData('text/plain', snapshot.id);
event.dataTransfer.setData('openmct/snapshot/id', snapshot.id);
},
updateSnapshot(snapshot) {
this.snapshotContainer.updateSnapshot(snapshot);
}
}
};

View File

@@ -18,18 +18,13 @@ export default class SnapshotContainer extends EventEmitter {
return SnapshotContainer.instance;
}
addSnapshot(notebookImageDomainObject, embedObject) {
addSnapshot(embedObject) {
const snapshots = this.getSnapshots();
if (snapshots.length >= NOTEBOOK_SNAPSHOT_MAX_COUNT) {
snapshots.pop();
}
const snapshotObject = {
notebookImageDomainObject,
embedObject
};
snapshots.unshift(snapshotObject);
snapshots.unshift(embedObject);
return this.saveSnapshots(snapshots);
}
@@ -37,7 +32,7 @@ export default class SnapshotContainer extends EventEmitter {
getSnapshot(id) {
const snapshots = this.getSnapshots();
return snapshots.find(s => s.embedObject.id === id);
return snapshots.find(s => s.id === id);
}
getSnapshots() {
@@ -52,7 +47,7 @@ export default class SnapshotContainer extends EventEmitter {
}
const snapshots = this.getSnapshots();
const filteredsnapshots = snapshots.filter(snapshot => snapshot.embedObject.id !== id);
const filteredsnapshots = snapshots.filter(snapshot => snapshot.id !== id);
return this.saveSnapshots(filteredsnapshots);
}
@@ -78,7 +73,7 @@ export default class SnapshotContainer extends EventEmitter {
updateSnapshot(snapshot) {
const snapshots = this.getSnapshots();
const updatedSnapshots = snapshots.map(s => {
return s.embedObject.id === snapshot.embedObject.id
return s.id === snapshot.id
? snapshot
: s;
});

View File

@@ -1,7 +1,7 @@
import { addNotebookEntry, createNewEmbed } from './utils/notebook-entries';
import { getDefaultNotebook, getNotebookSectionAndPage, getDefaultNotebookLink, setDefaultNotebook } from './utils/notebook-storage';
import { NOTEBOOK_DEFAULT } from '@/plugins/notebook/notebook-constants';
import { createNotebookImageDomainObject, saveNotebookImageDomainObject, updateNamespaceOfDomainObject, DEFAULT_SIZE } from './utils/notebook-image';
import { createNotebookImageDomainObject, DEFAULT_SIZE } from './utils/notebook-image';
import SnapshotContainer from './snapshot-container';
import ImageExporter from '../../exporters/ImageExporter';
@@ -35,28 +35,29 @@ export default class Snapshot {
* @private
*/
_saveSnapShot(notebookType, fullSizeImageURL, thumbnailImageURL, snapshotMeta) {
const object = createNotebookImageDomainObject(fullSizeImageURL);
const thumbnailImage = { src: thumbnailImageURL || '' };
const snapshot = {
fullSizeImageObjectIdentifier: object.identifier,
thumbnailImage
};
const embed = createNewEmbed(snapshotMeta, snapshot);
if (notebookType === NOTEBOOK_DEFAULT) {
const notebookStorage = getDefaultNotebook();
createNotebookImageDomainObject(this.openmct, fullSizeImageURL)
.then(object => {
const thumbnailImage = { src: thumbnailImageURL || '' };
const snapshot = {
fullSizeImageObjectIdentifier: object.identifier,
thumbnailImage
};
const embed = createNewEmbed(snapshotMeta, snapshot);
if (notebookType === NOTEBOOK_DEFAULT) {
this._saveToDefaultNoteBook(embed);
this._saveToDefaultNoteBook(notebookStorage, embed);
const notebookImageDomainObject = updateNamespaceOfDomainObject(object, notebookStorage.identifier.namespace);
saveNotebookImageDomainObject(this.openmct, notebookImageDomainObject);
} else {
this._saveToNotebookSnapshots(object, embed);
}
return;
}
this._saveToNotebookSnapshots(embed);
});
}
/**
* @private
*/
_saveToDefaultNoteBook(notebookStorage, embed) {
_saveToDefaultNoteBook(embed) {
const notebookStorage = getDefaultNotebook();
this.openmct.objects.get(notebookStorage.identifier)
.then(async (domainObject) => {
addNotebookEntry(this.openmct, domainObject, notebookStorage, embed);
@@ -84,22 +85,19 @@ export default class Snapshot {
/**
* @private
*/
_saveToNotebookSnapshots(notebookImageDomainObject, embed) {
this.snapshotContainer.addSnapshot(notebookImageDomainObject, embed);
_saveToNotebookSnapshots(embed) {
this.snapshotContainer.addSnapshot(embed);
}
_showNotification(msg, url) {
const options = {
autoDismissTimeout: 30000
};
if (!this.openmct.editor.isEditing()) {
options.link = {
autoDismissTimeout: 30000,
link: {
cssClass: '',
text: 'click to view',
onClick: this._navigateToNotebook(url)
};
}
}
};
this.openmct.notifications.info(msg, options);
}

View File

@@ -5,14 +5,14 @@ export const DEFAULT_SIZE = {
height: 30
};
export function createNotebookImageDomainObject(fullSizeImageURL) {
export function createNotebookImageDomainObject(openmct, fullSizeImageURL) {
const identifier = {
key: uuid(),
namespace: ''
};
const viewType = 'notebookSnapshotImage';
return {
const object = {
name: 'Notebook Snapshot Image',
type: viewType,
identifier,
@@ -20,6 +20,21 @@ export function createNotebookImageDomainObject(fullSizeImageURL) {
fullSizeImageURL
}
};
return new Promise((resolve, reject) => {
openmct.objects.save(object)
.then(result => {
if (result) {
resolve(object);
}
reject();
})
.catch(e => {
console.error(e);
reject();
});
});
}
export function getThumbnailURLFromCanvas(canvas, size = DEFAULT_SIZE) {
@@ -52,23 +67,6 @@ export function getThumbnailURLFromimageUrl(imageUrl, size = DEFAULT_SIZE) {
});
}
export function saveNotebookImageDomainObject(openmct, object) {
return new Promise((resolve, reject) => {
openmct.objects.save(object)
.then(result => {
if (result) {
resolve(object);
} else {
reject();
}
})
.catch(e => {
console.error(e);
reject();
});
});
}
export function updateNotebookImageDomainObject(openmct, identifier, fullSizeImage) {
openmct.objects.get(identifier)
.then(domainObject => {
@@ -78,9 +76,3 @@ export function updateNotebookImageDomainObject(openmct, identifier, fullSizeIma
openmct.objects.mutate(domainObject, 'configuration', configuration);
});
}
export function updateNamespaceOfDomainObject(object, namespace) {
object.identifier.namespace = namespace;
return object;
}

View File

@@ -1,18 +1,16 @@
import { createNotebookImageDomainObject, getThumbnailURLFromimageUrl, saveNotebookImageDomainObject, updateNamespaceOfDomainObject } from './notebook-image';
import { createNotebookImageDomainObject, getThumbnailURLFromimageUrl } from './notebook-image';
import { mutateObject } from './notebook-entries';
const IMAGE_MIGRATION_VER = "v1";
export function notebookImageMigration(openmct, domainObject) {
const configuration = domainObject.configuration;
const notebookEntries = configuration.entries;
const imageMigrationVer = configuration.imageMigrationVer;
if (imageMigrationVer && imageMigrationVer === IMAGE_MIGRATION_VER) {
if (imageMigrationVer && imageMigrationVer === 'v1') {
return;
}
configuration.imageMigrationVer = IMAGE_MIGRATION_VER;
configuration.imageMigrationVer = 'v1';
// to avoid muliple notebookImageMigration calls updating images.
mutateObject(openmct, domainObject, 'configuration', configuration);
@@ -29,16 +27,14 @@ export function notebookImageMigration(openmct, domainObject) {
const fullSizeImageURL = snapshot.src;
if (fullSizeImageURL) {
const thumbnailImageURL = await getThumbnailURLFromimageUrl(fullSizeImageURL);
const object = createNotebookImageDomainObject(fullSizeImageURL);
const notebookImageDomainObject = updateNamespaceOfDomainObject(object, domainObject.identifier.namespace);
const notebookImageDomainObject = await createNotebookImageDomainObject(openmct, fullSizeImageURL);
embed.snapshot = {
fullSizeImageObjectIdentifier: notebookImageDomainObject.identifier,
thumbnailImage: { src: thumbnailImageURL || '' }
};
mutateObject(openmct, domainObject, 'configuration.entries', notebookEntries);
saveNotebookImageDomainObject(openmct, notebookImageDomainObject);
}
});
});

View File

@@ -1,31 +0,0 @@
import { getDefaultNotebook, getNotebookSectionAndPage } from './notebook-storage';
export async function getMenuItems(openmct, menuItemOptions) {
const notebookTypes = [];
const defaultNotebook = getDefaultNotebook();
const defaultNotebookObject = defaultNotebook && await openmct.objects.get(defaultNotebook.identifier);
if (defaultNotebookObject) {
const { section, page } = getNotebookSectionAndPage(defaultNotebookObject, defaultNotebook.defaultSectionId, defaultNotebook.defaultPageId);
if (section && page) {
const name = defaultNotebookObject.name;
const sectionName = section.name;
const pageName = page.name;
const defaultPath = `${name} - ${sectionName} - ${pageName}`;
notebookTypes.push({
cssClass: menuItemOptions.default.cssClass,
name: `${menuItemOptions.default.name} ${defaultPath}`,
onItemClicked: menuItemOptions.default.onItemClicked
});
}
}
notebookTypes.push({
cssClass: menuItemOptions.snapshot.cssClass,
name: menuItemOptions.snapshot.name,
onItemClicked: menuItemOptions.snapshot.onItemClicked
});
return notebookTypes;
}

View File

@@ -71,7 +71,11 @@ export async function getDefaultNotebookLink(openmct, domainObject = null) {
}
const path = await openmct.objects.getOriginalPath(domainObject.identifier)
.then(openmct.objects.getRelativePath);
.then(objectPath => objectPath
.map(o => o && openmct.objects.makeKeyString(o.identifier))
.reverse()
.join('/')
);
const { defaultPageId, defaultSectionId } = getDefaultNotebook();
return `#/browse/${path}?sectionId=${defaultSectionId}&pageId=${defaultPageId}`;
@@ -99,13 +103,10 @@ export function validateNotebookStorageObject() {
let valid = false;
if (notebookStorage) {
const oldInvalidKeys = ['notebookMeta', 'page', 'section'];
valid = Object.entries(notebookStorage).every(([key, value]) => {
Object.entries(notebookStorage).forEach(([key, value]) => {
const validKey = key !== undefined && key !== null;
const validValue = value !== undefined && value !== null;
const hasOldInvalidKeys = oldInvalidKeys.includes(key);
return validKey && validValue && !hasOldInvalidKeys;
valid = validKey && validValue;
});
}

View File

@@ -25,16 +25,16 @@
:class="[plotLegendExpandedStateClass, plotLegendPositionClass]"
>
<plot-legend :cursor-locked="!!lockHighlightPoint"
:series="seriesModels"
:series="config.series.models"
:highlights="highlights"
:legend="legend"
:legend="config.legend"
@legendHoverChanged="legendHoverChanged"
/>
<div class="plot-wrapper-axis-and-display-area flex-elem grows">
<y-axis v-if="seriesModels.length > 0"
<y-axis v-if="config.series.models.length > 0"
:tick-width="tickWidth"
:single-series="seriesModels.length === 1"
:series-model="seriesModels[0]"
:single-series="config.series.models.length === 1"
:series-model="config.series.models[0]"
@yKeyChanged="setYAxisKey"
@tickWidthChanged="onTickWidthChange"
/>
@@ -141,8 +141,8 @@
>
</div>
</div>
<x-axis v-if="seriesModels.length > 0 && !options.compact"
:series-model="seriesModels[0]"
<x-axis v-if="config.series.models.length > 0 && !options.compact"
:series-model="config.series.models[0]"
/>
</div>
@@ -213,8 +213,7 @@ export default {
plotHistory: [],
selectedXKeyOption: {},
xKeyOptions: [],
seriesModels: [],
legend: {},
config: {},
pending: 0,
isRealTime: this.openmct.time.clock() !== undefined,
loaded: false,
@@ -240,13 +239,18 @@ export default {
watch: {
plotTickWidth(newTickWidth) {
this.onTickWidthChange(newTickWidth, true);
},
gridLines(newGridLines) {
this.setGridLinesVisibility(newGridLines);
},
cursorGuide(newCursorGuide) {
this.setCursorGuideVisibility(newCursorGuide);
}
},
mounted() {
eventHelpers.extend(this);
this.config = this.getConfig();
this.legend = this.config.legend;
this.listenTo(this.config.series, 'add', this.addSeries, this);
this.listenTo(this.config.series, 'remove', this.removeSeries, this);
@@ -286,18 +290,14 @@ export default {
config = new PlotConfigurationModel({
id: configId,
domainObject: this.domainObject,
openmct: this.openmct,
callback: (data) => {
this.data = data;
}
openmct: this.openmct
});
configStore.add(configId, config);
}
return config;
},
addSeries(series, index) {
this.$set(this.seriesModels, index, series);
addSeries(series) {
this.listenTo(series, 'change:xKey', (xKey) => {
this.setDisplayRange(series, xKey);
}, this);
@@ -323,8 +323,6 @@ export default {
return;
}
this.offsetWidth = this.$parent.$refs.plotWrapper.offsetWidth;
this.startLoading();
const options = {
size: this.$parent.$refs.plotWrapper.offsetWidth,
@@ -379,8 +377,11 @@ export default {
},
stopLoading() {
this.pending -= 1;
this.updateLoading();
//TODO: Is Vue.$nextTick ok to replace $scope.$evalAsync?
this.$nextTick().then(() => {
this.pending -= 1;
this.updateLoading();
});
},
updateLoading() {
@@ -393,31 +394,12 @@ export default {
});
},
clearSeries() {
clearData() {
this.config.series.forEach(function (series) {
series.reset();
});
},
compositionPathContainsId(domainObjectToClear) {
return domainObjectToClear.composition.some((compositionIdentifier) => {
return this.openmct.objects.areIdsEqual(compositionIdentifier, this.domainObject.identifier);
});
},
clearData(domainObjectToClear) {
// If we don't have an object to clear (global), or the IDs are equal, just clear the data.
// If we have an object to clear, but the IDs don't match, we need to check the composition
// of the object we've been asked to clear to see if it contains the id we're looking for.
// This happens with stacked plots for example.
// If we find the ID, clear the plot.
if (!domainObjectToClear
|| this.openmct.objects.areIdsEqual(domainObjectToClear.identifier, this.domainObject.identifier)
|| this.compositionPathContainsId(domainObjectToClear)) {
this.clearSeries();
}
},
setDisplayRange(series, xKey) {
if (this.config.series.length !== 1) {
return;
@@ -525,7 +507,7 @@ export default {
},
initialize() {
this.handleWindowResize = _.debounce(this.handleWindowResize, 500);
_.debounce(this.handleWindowResize, 400);
this.plotContainerResizeObserver = new ResizeObserver(this.handleWindowResize);
this.plotContainerResizeObserver.observe(this.$parent.$refs.plotWrapper);
@@ -641,7 +623,7 @@ export default {
this.config.series.models.forEach(series => delete series.closest);
} else {
this.highlights = this.config.series.models
.filter(series => series.getSeriesData().length > 0)
.filter(series => series.data.length > 0)
.map(series => {
series.closest = series.nearestPoint(point);
@@ -945,6 +927,14 @@ export default {
this.userViewportChangeEnd();
},
setCursorGuideVisibility(cursorGuide) {
this.cursorGuide = cursorGuide === true;
},
setGridLinesVisibility(gridLines) {
this.gridLines = gridLines === true;
},
setYAxisKey(yKey) {
this.config.series.models[0].set('yKey', yKey);
},

View File

@@ -106,9 +106,8 @@ export default {
},
toggleXKeyOption() {
const selectedXKey = this.selectedXKeyOptionKey;
const seriesData = this.seriesModel.getSeriesData();
const dataForSelectedXKey = seriesData
? seriesData[0][selectedXKey]
const dataForSelectedXKey = this.seriesModel.data
? this.seriesModel.data[0][selectedXKey]
: undefined;
if (dataForSelectedXKey !== undefined) {

View File

@@ -36,7 +36,7 @@ export default class MCTChartAlarmPointSet {
this.listenTo(series, 'reset', this.reset, this);
this.listenTo(series, 'destroy', this.destroy, this);
this.series.getSeriesData().forEach(function (point, index) {
series.data.forEach(function (point, index) {
this.append(point, index, series);
}, this);
}

View File

@@ -36,7 +36,7 @@ export default class MCTChartSeriesElement {
this.listenTo(series, 'remove', this.remove, this);
this.listenTo(series, 'reset', this.reset, this);
this.listenTo(series, 'destroy', this.destroy, this);
this.series.getSeriesData().forEach(function (point, index) {
series.data.forEach(function (point, index) {
this.append(point, index, series);
}, this);
}
@@ -133,7 +133,7 @@ export default class MCTChartSeriesElement {
this.buffer = new Float32Array(20000);
this.count = 0;
if (this.offset.x) {
this.series.getSeriesData().forEach(function (point, index) {
this.series.data.forEach(function (point, index) {
this.append(point, index, this.series);
}, this);
}

View File

@@ -107,7 +107,6 @@ export default class PlotConfigurationModel extends Model {
updateDomainObject(domainObject) {
this.set('domainObject', domainObject);
}
/**
* Clean up all objects and remove all listeners.
*/

View File

@@ -22,7 +22,6 @@
import _ from 'lodash';
import Model from "./Model";
import { MARKER_SHAPES } from '../draw/MarkerShapes';
import configStore from "../configuration/configStore";
/**
* Plot series handle interpreting telemetry metadata for a single telemetry
@@ -63,6 +62,7 @@ import configStore from "../configuration/configStore";
export default class PlotSeries extends Model {
constructor(options) {
super(options);
this.data = [];
this.listenTo(this, 'change:xKey', this.onXKeyChange, this);
this.listenTo(this, 'change:yKey', this.onYKeyChange, this);
@@ -115,8 +115,6 @@ export default class PlotSeries extends Model {
this.openmct = options.openmct;
this.domainObject = options.domainObject;
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
this.dataStoreId = `data-${options.collection.plot.id}-${this.keyString}`;
this.updateSeriesData([]);
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(options.domainObject);
this.limitDefinition = this.openmct.telemetry.limitDefinition(options.domainObject);
this.limits = [];
@@ -184,8 +182,7 @@ export default class PlotSeries extends Model {
.telemetry
.request(this.domainObject, options)
.then(function (points) {
const data = this.getSeriesData();
const newPoints = _(data)
const newPoints = _(this.data)
.concat(points)
.sortBy(this.getXVal)
.uniq(true, point => [this.getXVal(point), this.getYVal(point)].join())
@@ -239,7 +236,7 @@ export default class PlotSeries extends Model {
*/
resetStats() {
this.unset('stats');
this.getSeriesData().forEach(this.updateStats, this);
this.data.forEach(this.updateStats, this);
}
/**
@@ -247,7 +244,7 @@ export default class PlotSeries extends Model {
* data to series after reset.
*/
reset(newData) {
this.updateSeriesData([]);
this.data = [];
this.resetStats();
this.emit('reset');
if (newData) {
@@ -261,9 +258,8 @@ export default class PlotSeries extends Model {
*/
nearestPoint(xValue) {
const insertIndex = this.sortedIndex(xValue);
const data = this.getSeriesData();
const lowPoint = data[insertIndex - 1];
const highPoint = data[insertIndex];
const lowPoint = this.data[insertIndex - 1];
const highPoint = this.data[insertIndex];
const indexVal = this.getXVal(xValue);
const lowDistance = lowPoint
? indexVal - this.getXVal(lowPoint)
@@ -296,7 +292,7 @@ export default class PlotSeries extends Model {
* @private
*/
sortedIndex(point) {
return _.sortedIndexBy(this.getSeriesData(), point, this.getXVal);
return _.sortedIndexBy(this.data, point, this.getXVal);
}
/**
* Update min/max stats for the series.
@@ -350,10 +346,9 @@ export default class PlotSeries extends Model {
* a point to the end without dupe checking.
*/
add(point, appendOnly) {
let data = this.getSeriesData();
let insertIndex = data.length;
let insertIndex = this.data.length;
const currentYVal = this.getYVal(point);
const lastYVal = this.getYVal(data[insertIndex - 1]);
const lastYVal = this.getYVal(this.data[insertIndex - 1]);
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
console.warn('[Plot] Invalid Y Values detected');
@@ -363,19 +358,18 @@ export default class PlotSeries extends Model {
if (!appendOnly) {
insertIndex = this.sortedIndex(point);
if (this.getXVal(data[insertIndex]) === this.getXVal(point)) {
if (this.getXVal(this.data[insertIndex]) === this.getXVal(point)) {
return;
}
if (this.getXVal(data[insertIndex - 1]) === this.getXVal(point)) {
if (this.getXVal(this.data[insertIndex - 1]) === this.getXVal(point)) {
return;
}
}
this.updateStats(point);
point.mctLimitState = this.evaluate(point);
data.splice(insertIndex, 0, point);
this.updateSeriesData(data);
this.data.splice(insertIndex, 0, point);
this.emit('add', point, insertIndex, this);
}
@@ -392,10 +386,8 @@ export default class PlotSeries extends Model {
* @private
*/
remove(point) {
let data = this.getSeriesData();
const index = data.indexOf(point);
data.splice(index, 1);
this.updateSeriesData(data);
const index = this.data.indexOf(point);
this.data.splice(index, 1);
this.emit('remove', point, index, this);
}
/**
@@ -411,16 +403,14 @@ export default class PlotSeries extends Model {
purgeRecordsOutsideRange(range) {
const startIndex = this.sortedIndex(range.min);
const endIndex = this.sortedIndex(range.max) + 1;
let data = this.getSeriesData();
const pointsToRemove = startIndex + (data.length - endIndex + 1);
const pointsToRemove = startIndex + (this.data.length - endIndex + 1);
if (pointsToRemove > 0) {
if (pointsToRemove < 1000) {
data.slice(0, startIndex).forEach(this.remove, this);
data.slice(endIndex, data.length).forEach(this.remove, this);
this.updateSeriesData(data);
this.data.slice(0, startIndex).forEach(this.remove, this);
this.data.slice(endIndex, this.data.length).forEach(this.remove, this);
this.resetStats();
} else {
const newData = this.getSeriesData().slice(startIndex, endIndex);
const newData = this.data.slice(startIndex, endIndex);
this.reset(newData);
}
}
@@ -451,13 +441,12 @@ export default class PlotSeries extends Model {
}
}
getDisplayRange(xKey) {
const unsortedData = this.getSeriesData();
this.updateSeriesData([]);
const unsortedData = this.data;
this.data = [];
unsortedData.forEach(point => this.add(point, false));
let data = this.getSeriesData();
const minValue = this.getXVal(data[0]);
const maxValue = this.getXVal(data[data.length - 1]);
const minValue = this.getXVal(this.data[0]);
const maxValue = this.getXVal(this.data[this.data.length - 1]);
return {
min: minValue,
@@ -481,18 +470,4 @@ export default class PlotSeries extends Model {
return this.get('name') + (unit ? ' ' + unit : '');
}
/**
* Update the series data with the given value.
*/
updateSeriesData(data) {
configStore.add(this.dataStoreId, data);
}
/**
* Update the series data with the given value.
*/
getSeriesData() {
return configStore.get(this.dataStoreId) || [];
}
}

View File

@@ -25,10 +25,7 @@ function ConfigStore() {
ConfigStore.prototype.deleteStore = function (id) {
if (this.store[id]) {
if (this.store[id].destroy) {
this.store[id].destroy();
}
this.store[id].destroy();
delete this.store[id];
}
};

View File

@@ -176,9 +176,7 @@ DrawWebGL.prototype.doDraw = function (drawType, buf, color, points, shape) {
this.gl.vertexAttribPointer(this.aVertexPosition, 2, this.gl.FLOAT, false, 0, 0);
this.gl.uniform4fv(this.uColor, color);
this.gl.uniform1i(this.uMarkerShape, shapeCode);
if (points !== 0) {
this.gl.drawArrays(drawType, 0, points);
}
this.gl.drawArrays(drawType, 0, points);
};
DrawWebGL.prototype.clear = function () {

View File

@@ -715,15 +715,14 @@ describe("the plugin", function () {
});
it("Adds a new point to the plot", (done) => {
let originalLength = config.series.models[0].getSeriesData().length;
let originalLength = config.series.models[0].data.length;
config.series.models[0].add({
utc: 2,
'some-key': 1,
'some-other-key': 2
});
Vue.nextTick(() => {
const seriesData = config.series.models[0].getSeriesData();
expect(seriesData.length).toEqual(originalLength + 1);
expect(config.series.models[0].data.length).toEqual(originalLength + 1);
done();
});
});

View File

@@ -68,8 +68,7 @@ define([
'./performanceIndicator/plugin',
'./CouchDBSearchFolder/plugin',
'./timeline/plugin',
'./hyperlink/plugin',
'./DeviceClassifier/plugin'
'./hyperlink/plugin'
], function (
_,
UTCTimeSystem,
@@ -118,8 +117,7 @@ define([
PerformanceIndicator,
CouchDBSearchFolder,
Timeline,
Hyperlink,
DeviceClassifier
Hyperlink
) {
const bundleMap = {
LocalStorage: 'platform/persistence/local',
@@ -223,7 +221,6 @@ define([
plugins.CouchDBSearchFolder = CouchDBSearchFolder.default;
plugins.Timeline = Timeline.default;
plugins.Hyperlink = Hyperlink.default;
plugins.DeviceClassifier = DeviceClassifier.default;
return plugins;
});

View File

@@ -36,7 +36,7 @@ define([
}
/**
* Converts all objects in an object make from old format objects to new
* Convets all objects in an object make from old format objects to new
* format objects.
*/
function convertToNewObjects(oldObjectMap) {

View File

@@ -115,7 +115,7 @@ define([
expect(condition.evaluate(telemetryState)).toBe(true);
});
it('can evaluate "if any object matches"', function () {
it('can evalute "if any object matches"', function () {
condition = new SummaryWidgetCondition({
object: 'any',
key: 'raw',

View File

@@ -379,7 +379,7 @@ define(['../src/ConditionManager'], function (ConditionManager) {
telemetryRequests[1].resolve([mockTelemetryValues.mockCompObject2]);
});
it('updates its LAD cache upon receiving telemetry and invokes the appropriate handlers', function () {
it('updates its LAD cache upon recieving telemetry and invokes the appropriate handlers', function () {
mockTelemetryAPI.triggerTelemetryCallback('mockCompObject1');
expect(conditionManager.subscriptionCache.mockCompObject1.property1).toEqual('Its a different string');
mockTelemetryAPI.triggerTelemetryCallback('mockCompObject2');

View File

@@ -48,7 +48,7 @@
display: flex;
flex-flow: column nowrap;
flex: 1 1 auto;
height: 0; // Chrome 73 overflow bug fix
height: 0; // Chrome 73 oveflow bug fix
}
&__empty-message {

View File

@@ -149,7 +149,7 @@ define([
this.removeTelemetryCollection(keyString);
this.telemetryCollections[keyString] = this.openmct.telemetry
.requestCollection(telemetryObject, requestOptions);
.requestTelemetryCollection(telemetryObject, requestOptions);
this.telemetryCollections[keyString].on('remove', telemetryRemover);
this.telemetryCollections[keyString].on('add', telemetryProcessor);

View File

@@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import Preview from '@/ui/preview/Preview.vue';
import PreviewHeader from '@/ui/preview/preview-header.vue';
import Vue from 'vue';
@@ -46,7 +46,7 @@ export default class ViewLargeAction {
throw new Error(message);
}
this._expand(objectPath, childElement);
this._expand(objectPath, childElement, view);
}
appliesTo(objectPath, view = {}) {
@@ -58,29 +58,49 @@ export default class ViewLargeAction {
return viewLargeAction;
}
_expand(objectPath, childElement) {
_expand(objectPath, childElement, view) {
const parentElement = childElement.parentElement;
this.overlay = this.openmct.overlays.overlay({
element: this._getPreview(objectPath),
element: this._getOverlayElement(objectPath, childElement, view),
size: 'large',
autoHide: false,
onDestroy() {
parentElement.append(childElement);
}
});
}
_getPreview(objectPath) {
_getOverlayElement(objectPath, childElement, view) {
const fragment = new DocumentFragment();
const header = this._getPreviewHeader(objectPath, view);
fragment.append(header);
const wrapper = document.createElement('div');
wrapper.classList.add('l-preview-window__object-view');
wrapper.append(childElement);
fragment.append(wrapper);
return fragment;
}
_getPreviewHeader(objectPath, view) {
const domainObject = objectPath[0];
const actionCollection = this.openmct.actions.getActionsCollection(objectPath, view);
const preview = new Vue({
components: {
Preview
PreviewHeader
},
provide: {
openmct: this.openmct,
objectPath
objectPath: this.objectPath
},
template: '<Preview></Preview>'
data() {
return {
domainObject,
actionCollection
};
},
template: '<PreviewHeader :actionCollection="actionCollection" :domainObject="domainObject" :hideViewSwitcher="true" :showNotebookMenuSwitcher="true"></PreviewHeader>'
});
return preview.$mount().$el;

View File

@@ -154,7 +154,6 @@ $glyph-icon-flag: '\e92a';
$glyph-icon-eye-disabled: '\e92b';
$glyph-icon-notebook-page: '\e92c';
$glyph-icon-unlocked: '\e92d';
$glyph-icon-circle: '\e92e';
$glyph-icon-arrows-right-left: '\ea00';
$glyph-icon-arrows-up-down: '\ea01';
$glyph-icon-bullet: '\ea02';
@@ -258,7 +257,6 @@ $glyph-icon-conditional: '\eb27';
$glyph-icon-condition-widget: '\eb28';
$glyph-icon-alphanumeric: '\eb29';
$glyph-icon-image-telemetry: '\eb2a';
$glyph-icon-telemetry-aggregate: '\eb2b';
/************************** GLYPHS AS DATA URI */
// Only objects have been converted, for use in Create menu and folder views

View File

@@ -85,7 +85,6 @@
.icon-eye-disabled { @include glyphBefore($glyph-icon-eye-disabled); }
.icon-notebook-page { @include glyphBefore($glyph-icon-notebook-page); }
.icon-unlocked { @include glyphBefore($glyph-icon-unlocked); }
.icon-circle { @include glyphBefore($glyph-icon-circle); }
.icon-arrows-right-left { @include glyphBefore($glyph-icon-arrows-right-left); }
.icon-arrows-up-down { @include glyphBefore($glyph-icon-arrows-up-down); }
.icon-bullet { @include glyphBefore($glyph-icon-bullet); }
@@ -189,7 +188,6 @@
.icon-condition-widget { @include glyphBefore($glyph-icon-condition-widget); }
.icon-alphanumeric { @include glyphBefore($glyph-icon-alphanumeric); }
.icon-image-telemetry { @include glyphBefore($glyph-icon-image-telemetry); }
.icon-telemetry-aggregate { @include glyphBefore($glyph-icon-telemetry-aggregate); }
/************************** 12 PX CLASSES */
// TODO: sync with 16px redo as of 10/25/18

View File

@@ -2,7 +2,7 @@
"metadata": {
"name": "Open MCT Symbols 16px",
"lastOpened": 0,
"created": 1629996145999
"created": 1621648023886
},
"iconSets": [
{
@@ -375,21 +375,13 @@
"code": 59693,
"tempChar": ""
},
{
"order": 197,
"id": 169,
"name": "icon-circle",
"prevSize": 24,
"code": 59694,
"tempChar": ""
},
{
"order": 27,
"id": 105,
"name": "icon-arrows-right-left",
"prevSize": 24,
"code": 59904,
"tempChar": ""
"tempChar": ""
},
{
"order": 26,
@@ -397,7 +389,7 @@
"name": "icon-arrows-up-down",
"prevSize": 24,
"code": 59905,
"tempChar": ""
"tempChar": ""
},
{
"order": 68,
@@ -405,7 +397,7 @@
"name": "icon-bullet",
"prevSize": 24,
"code": 59906,
"tempChar": ""
"tempChar": ""
},
{
"order": 150,
@@ -413,7 +405,7 @@
"prevSize": 24,
"code": 59907,
"name": "icon-calendar",
"tempChar": ""
"tempChar": ""
},
{
"order": 45,
@@ -421,7 +413,7 @@
"name": "icon-chain-links",
"prevSize": 24,
"code": 59908,
"tempChar": ""
"tempChar": ""
},
{
"order": 73,
@@ -429,7 +421,7 @@
"name": "icon-download",
"prevSize": 24,
"code": 59909,
"tempChar": ""
"tempChar": ""
},
{
"order": 39,
@@ -437,7 +429,7 @@
"name": "icon-duplicate",
"prevSize": 24,
"code": 59910,
"tempChar": ""
"tempChar": ""
},
{
"order": 50,
@@ -445,7 +437,7 @@
"name": "icon-folder-new",
"prevSize": 24,
"code": 59911,
"tempChar": ""
"tempChar": ""
},
{
"order": 138,
@@ -453,7 +445,7 @@
"name": "icon-fullscreen-collapse",
"prevSize": 24,
"code": 59912,
"tempChar": ""
"tempChar": ""
},
{
"order": 139,
@@ -461,7 +453,7 @@
"name": "icon-fullscreen-expand",
"prevSize": 24,
"code": 59913,
"tempChar": ""
"tempChar": ""
},
{
"order": 122,
@@ -469,7 +461,7 @@
"name": "icon-layers",
"prevSize": 24,
"code": 59914,
"tempChar": ""
"tempChar": ""
},
{
"order": 151,
@@ -477,7 +469,7 @@
"name": "icon-line-horz",
"prevSize": 24,
"code": 59915,
"tempChar": ""
"tempChar": ""
},
{
"order": 100,
@@ -485,7 +477,7 @@
"name": "icon-magnify",
"prevSize": 24,
"code": 59916,
"tempChar": ""
"tempChar": ""
},
{
"order": 99,
@@ -493,7 +485,7 @@
"name": "icon-magnify-in",
"prevSize": 24,
"code": 59917,
"tempChar": ""
"tempChar": ""
},
{
"order": 101,
@@ -501,7 +493,7 @@
"name": "icon-magnify-out-v2",
"prevSize": 24,
"code": 59918,
"tempChar": ""
"tempChar": ""
},
{
"order": 103,
@@ -509,7 +501,7 @@
"name": "icon-menu",
"prevSize": 24,
"code": 59919,
"tempChar": ""
"tempChar": ""
},
{
"order": 124,
@@ -517,7 +509,7 @@
"name": "icon-move",
"prevSize": 24,
"code": 59920,
"tempChar": ""
"tempChar": ""
},
{
"order": 7,
@@ -525,7 +517,7 @@
"name": "icon-new-window",
"prevSize": 24,
"code": 59921,
"tempChar": ""
"tempChar": ""
},
{
"order": 63,
@@ -533,7 +525,7 @@
"name": "icon-paint-bucket-v2",
"prevSize": 24,
"code": 59922,
"tempChar": ""
"tempChar": ""
},
{
"order": 15,
@@ -541,7 +533,7 @@
"name": "icon-pencil",
"prevSize": 24,
"code": 59923,
"tempChar": ""
"tempChar": ""
},
{
"order": 54,
@@ -549,7 +541,7 @@
"name": "icon-pencil-edit-in-place",
"prevSize": 24,
"code": 59924,
"tempChar": ""
"tempChar": ""
},
{
"order": 40,
@@ -557,7 +549,7 @@
"name": "icon-play",
"prevSize": 24,
"code": 59925,
"tempChar": ""
"tempChar": ""
},
{
"order": 125,
@@ -565,7 +557,7 @@
"name": "icon-pause",
"prevSize": 24,
"code": 59926,
"tempChar": ""
"tempChar": ""
},
{
"order": 119,
@@ -573,7 +565,7 @@
"name": "icon-plot-resource",
"prevSize": 24,
"code": 59927,
"tempChar": ""
"tempChar": ""
},
{
"order": 48,
@@ -581,7 +573,7 @@
"name": "icon-pointer-left",
"prevSize": 24,
"code": 59928,
"tempChar": ""
"tempChar": ""
},
{
"order": 47,
@@ -589,7 +581,7 @@
"name": "icon-pointer-right",
"prevSize": 24,
"code": 59929,
"tempChar": ""
"tempChar": ""
},
{
"order": 85,
@@ -597,7 +589,7 @@
"name": "icon-refresh",
"prevSize": 24,
"code": 59930,
"tempChar": ""
"tempChar": ""
},
{
"order": 55,
@@ -605,7 +597,7 @@
"name": "icon-save",
"prevSize": 24,
"code": 59931,
"tempChar": ""
"tempChar": ""
},
{
"order": 56,
@@ -613,7 +605,7 @@
"name": "icon-save-as",
"prevSize": 24,
"code": 59932,
"tempChar": ""
"tempChar": ""
},
{
"order": 58,
@@ -621,7 +613,7 @@
"name": "icon-sine",
"prevSize": 24,
"code": 59933,
"tempChar": ""
"tempChar": ""
},
{
"order": 113,
@@ -629,7 +621,7 @@
"name": "icon-font",
"prevSize": 24,
"code": 59934,
"tempChar": ""
"tempChar": ""
},
{
"order": 41,
@@ -637,7 +629,7 @@
"name": "icon-thumbs-strip",
"prevSize": 24,
"code": 59935,
"tempChar": ""
"tempChar": ""
},
{
"order": 146,
@@ -645,7 +637,7 @@
"name": "icon-two-parts-both",
"prevSize": 24,
"code": 59936,
"tempChar": ""
"tempChar": ""
},
{
"order": 145,
@@ -653,7 +645,7 @@
"name": "icon-two-parts-one-only",
"prevSize": 24,
"code": 59937,
"tempChar": ""
"tempChar": ""
},
{
"order": 82,
@@ -661,7 +653,7 @@
"name": "icon-resync",
"prevSize": 24,
"code": 59938,
"tempChar": ""
"tempChar": ""
},
{
"order": 86,
@@ -669,7 +661,7 @@
"name": "icon-reset",
"prevSize": 24,
"code": 59939,
"tempChar": ""
"tempChar": ""
},
{
"order": 61,
@@ -677,7 +669,7 @@
"name": "icon-x-in-circle",
"prevSize": 24,
"code": 59940,
"tempChar": ""
"tempChar": ""
},
{
"order": 84,
@@ -685,7 +677,7 @@
"name": "icon-brightness",
"prevSize": 24,
"code": 59941,
"tempChar": ""
"tempChar": ""
},
{
"order": 83,
@@ -693,7 +685,7 @@
"name": "icon-contrast",
"prevSize": 24,
"code": 59942,
"tempChar": ""
"tempChar": ""
},
{
"order": 87,
@@ -701,7 +693,7 @@
"name": "icon-expand",
"prevSize": 24,
"code": 59943,
"tempChar": ""
"tempChar": ""
},
{
"order": 89,
@@ -709,7 +701,7 @@
"name": "icon-list-view",
"prevSize": 24,
"code": 59944,
"tempChar": ""
"tempChar": ""
},
{
"order": 133,
@@ -717,7 +709,7 @@
"name": "icon-grid-snap-to",
"prevSize": 24,
"code": 59945,
"tempChar": ""
"tempChar": ""
},
{
"order": 132,
@@ -725,7 +717,7 @@
"name": "icon-grid-snap-no",
"prevSize": 24,
"code": 59946,
"tempChar": ""
"tempChar": ""
},
{
"order": 94,
@@ -733,7 +725,7 @@
"name": "icon-frame-show",
"prevSize": 24,
"code": 59947,
"tempChar": ""
"tempChar": ""
},
{
"order": 95,
@@ -741,7 +733,7 @@
"name": "icon-frame-hide",
"prevSize": 24,
"code": 59948,
"tempChar": ""
"tempChar": ""
},
{
"order": 97,
@@ -749,7 +741,7 @@
"name": "icon-import",
"prevSize": 24,
"code": 59949,
"tempChar": ""
"tempChar": ""
},
{
"order": 96,
@@ -757,7 +749,7 @@
"name": "icon-export",
"prevSize": 24,
"code": 59950,
"tempChar": ""
"tempChar": ""
},
{
"order": 194,
@@ -765,7 +757,7 @@
"name": "icon-font-size",
"prevSize": 24,
"code": 59951,
"tempChar": ""
"tempChar": ""
},
{
"order": 163,
@@ -773,7 +765,7 @@
"name": "icon-clear-data",
"prevSize": 24,
"code": 59952,
"tempChar": ""
"tempChar": ""
},
{
"order": 173,
@@ -781,7 +773,7 @@
"name": "icon-history",
"prevSize": 24,
"code": 59953,
"tempChar": ""
"tempChar": ""
},
{
"order": 181,
@@ -789,7 +781,7 @@
"name": "icon-arrow-up-to-parent",
"prevSize": 24,
"code": 59954,
"tempChar": ""
"tempChar": ""
},
{
"order": 184,
@@ -797,7 +789,7 @@
"name": "icon-crosshair-in-circle",
"prevSize": 24,
"code": 59955,
"tempChar": ""
"tempChar": ""
},
{
"order": 185,
@@ -805,7 +797,7 @@
"name": "icon-target",
"prevSize": 24,
"code": 59956,
"tempChar": ""
"tempChar": ""
},
{
"order": 187,
@@ -813,7 +805,7 @@
"name": "icon-items-collapse",
"prevSize": 24,
"code": 59957,
"tempChar": ""
"tempChar": ""
},
{
"order": 188,
@@ -821,7 +813,7 @@
"name": "icon-items-expand",
"prevSize": 24,
"code": 59958,
"tempChar": ""
"tempChar": ""
},
{
"order": 190,
@@ -829,7 +821,7 @@
"name": "icon-3-dots",
"prevSize": 24,
"code": 59959,
"tempChar": ""
"tempChar": ""
},
{
"order": 193,
@@ -837,7 +829,7 @@
"name": "icon-grid-on",
"prevSize": 24,
"code": 59960,
"tempChar": ""
"tempChar": ""
},
{
"order": 192,
@@ -845,7 +837,7 @@
"name": "icon-grid-off",
"prevSize": 24,
"code": 59961,
"tempChar": ""
"tempChar": ""
},
{
"order": 191,
@@ -853,7 +845,7 @@
"name": "icon-camera",
"prevSize": 24,
"code": 59962,
"tempChar": ""
"tempChar": ""
},
{
"order": 196,
@@ -861,7 +853,7 @@
"name": "icon-folders-collapse",
"prevSize": 24,
"code": 59963,
"tempChar": ""
"tempChar": ""
},
{
"order": 144,
@@ -869,7 +861,7 @@
"name": "icon-activity",
"prevSize": 24,
"code": 60160,
"tempChar": ""
"tempChar": ""
},
{
"order": 104,
@@ -877,7 +869,7 @@
"name": "icon-activity-mode",
"prevSize": 24,
"code": 60161,
"tempChar": ""
"tempChar": ""
},
{
"order": 137,
@@ -885,7 +877,7 @@
"name": "icon-autoflow-tabular",
"prevSize": 24,
"code": 60162,
"tempChar": ""
"tempChar": ""
},
{
"order": 115,
@@ -893,7 +885,7 @@
"name": "icon-clock",
"prevSize": 24,
"code": 60163,
"tempChar": ""
"tempChar": ""
},
{
"order": 2,
@@ -901,7 +893,7 @@
"name": "icon-database",
"prevSize": 24,
"code": 60164,
"tempChar": ""
"tempChar": ""
},
{
"order": 3,
@@ -909,7 +901,7 @@
"name": "icon-database-query",
"prevSize": 24,
"code": 60165,
"tempChar": ""
"tempChar": ""
},
{
"order": 67,
@@ -917,7 +909,7 @@
"name": "icon-dataset",
"prevSize": 24,
"code": 60166,
"tempChar": ""
"tempChar": ""
},
{
"order": 59,
@@ -925,7 +917,7 @@
"name": "icon-datatable",
"prevSize": 24,
"code": 60167,
"tempChar": ""
"tempChar": ""
},
{
"order": 136,
@@ -933,7 +925,7 @@
"name": "icon-dictionary",
"prevSize": 24,
"code": 60168,
"tempChar": ""
"tempChar": ""
},
{
"order": 51,
@@ -941,7 +933,7 @@
"name": "icon-folder",
"prevSize": 24,
"code": 60169,
"tempChar": ""
"tempChar": ""
},
{
"order": 147,
@@ -949,7 +941,7 @@
"name": "icon-image",
"prevSize": 24,
"code": 60170,
"tempChar": ""
"tempChar": ""
},
{
"order": 4,
@@ -957,7 +949,7 @@
"name": "icon-layout",
"prevSize": 24,
"code": 60171,
"tempChar": ""
"tempChar": ""
},
{
"order": 24,
@@ -965,7 +957,7 @@
"name": "icon-object",
"prevSize": 24,
"code": 60172,
"tempChar": ""
"tempChar": ""
},
{
"order": 52,
@@ -973,7 +965,7 @@
"name": "icon-object-unknown",
"prevSize": 24,
"code": 60173,
"tempChar": ""
"tempChar": ""
},
{
"order": 105,
@@ -981,7 +973,7 @@
"name": "icon-packet",
"prevSize": 24,
"code": 60174,
"tempChar": ""
"tempChar": ""
},
{
"order": 126,
@@ -989,7 +981,7 @@
"name": "icon-page",
"prevSize": 24,
"code": 60175,
"tempChar": ""
"tempChar": ""
},
{
"order": 130,
@@ -997,7 +989,7 @@
"name": "icon-plot-overlay",
"prevSize": 24,
"code": 60176,
"tempChar": ""
"tempChar": ""
},
{
"order": 80,
@@ -1005,7 +997,7 @@
"name": "icon-plot-stacked",
"prevSize": 24,
"code": 60177,
"tempChar": ""
"tempChar": ""
},
{
"order": 134,
@@ -1013,7 +1005,7 @@
"name": "icon-session",
"prevSize": 24,
"code": 60178,
"tempChar": ""
"tempChar": ""
},
{
"order": 109,
@@ -1021,7 +1013,7 @@
"name": "icon-tabular",
"prevSize": 24,
"code": 60179,
"tempChar": ""
"tempChar": ""
},
{
"order": 107,
@@ -1029,7 +1021,7 @@
"name": "icon-tabular-lad",
"prevSize": 24,
"code": 60180,
"tempChar": ""
"tempChar": ""
},
{
"order": 106,
@@ -1037,7 +1029,7 @@
"name": "icon-tabular-lad-set",
"prevSize": 24,
"code": 60181,
"tempChar": ""
"tempChar": ""
},
{
"order": 70,
@@ -1045,7 +1037,7 @@
"name": "icon-tabular-realtime",
"prevSize": 24,
"code": 60182,
"tempChar": ""
"tempChar": ""
},
{
"order": 60,
@@ -1053,7 +1045,7 @@
"name": "icon-tabular-scrolling",
"prevSize": 24,
"code": 60183,
"tempChar": ""
"tempChar": ""
},
{
"order": 131,
@@ -1061,7 +1053,7 @@
"name": "icon-telemetry",
"prevSize": 24,
"code": 60184,
"tempChar": ""
"tempChar": ""
},
{
"order": 108,
@@ -1069,7 +1061,7 @@
"name": "icon-timeline",
"prevSize": 24,
"code": 60185,
"tempChar": ""
"tempChar": ""
},
{
"order": 81,
@@ -1077,7 +1069,7 @@
"name": "icon-timer",
"prevSize": 24,
"code": 60186,
"tempChar": ""
"tempChar": ""
},
{
"order": 69,
@@ -1085,7 +1077,7 @@
"name": "icon-topic",
"prevSize": 24,
"code": 60187,
"tempChar": ""
"tempChar": ""
},
{
"order": 79,
@@ -1093,7 +1085,7 @@
"name": "icon-box-with-dashed-lines-v2",
"prevSize": 24,
"code": 60188,
"tempChar": ""
"tempChar": ""
},
{
"order": 90,
@@ -1101,7 +1093,7 @@
"name": "icon-summary-widget",
"prevSize": 24,
"code": 60189,
"tempChar": ""
"tempChar": ""
},
{
"order": 92,
@@ -1109,7 +1101,7 @@
"name": "icon-notebook",
"prevSize": 24,
"code": 60190,
"tempChar": ""
"tempChar": ""
},
{
"order": 168,
@@ -1117,7 +1109,7 @@
"name": "icon-tabs-view",
"prevSize": 24,
"code": 60191,
"tempChar": ""
"tempChar": ""
},
{
"order": 117,
@@ -1125,7 +1117,7 @@
"name": "icon-flexible-layout",
"prevSize": 24,
"code": 60192,
"tempChar": ""
"tempChar": ""
},
{
"order": 166,
@@ -1133,7 +1125,7 @@
"name": "icon-generator-sine",
"prevSize": 24,
"code": 60193,
"tempChar": ""
"tempChar": ""
},
{
"order": 167,
@@ -1141,7 +1133,7 @@
"name": "icon-generator-event",
"prevSize": 24,
"code": 60194,
"tempChar": ""
"tempChar": ""
},
{
"order": 165,
@@ -1149,7 +1141,7 @@
"name": "icon-gauge-v2",
"prevSize": 24,
"code": 60195,
"tempChar": ""
"tempChar": ""
},
{
"order": 170,
@@ -1157,7 +1149,7 @@
"name": "icon-spectra",
"prevSize": 24,
"code": 60196,
"tempChar": ""
"tempChar": ""
},
{
"order": 171,
@@ -1165,7 +1157,7 @@
"name": "icon-telemetry-spectra",
"prevSize": 24,
"code": 60197,
"tempChar": ""
"tempChar": ""
},
{
"order": 172,
@@ -1173,7 +1165,7 @@
"name": "icon-pushbutton",
"prevSize": 24,
"code": 60198,
"tempChar": ""
"tempChar": ""
},
{
"order": 174,
@@ -1181,7 +1173,7 @@
"name": "icon-conditional",
"prevSize": 24,
"code": 60199,
"tempChar": ""
"tempChar": ""
},
{
"order": 178,
@@ -1189,7 +1181,7 @@
"name": "icon-condition-widget",
"prevSize": 24,
"code": 60200,
"tempChar": ""
"tempChar": ""
},
{
"order": 180,
@@ -1197,7 +1189,7 @@
"name": "icon-alphanumeric",
"prevSize": 24,
"code": 60201,
"tempChar": ""
"tempChar": ""
},
{
"order": 183,
@@ -1205,15 +1197,7 @@
"name": "icon-image-telemetry",
"prevSize": 24,
"code": 60202,
"tempChar": ""
},
{
"order": 198,
"id": 170,
"name": "icon-telemetry-aggregate",
"prevSize": 24,
"code": 60203,
"tempChar": ""
"tempChar": ""
}
],
"id": 0,
@@ -2016,26 +2000,6 @@
]
}
},
{
"id": 169,
"paths": [
"M1024 512c0 282.77-229.23 512-512 512s-512-229.23-512-512c0-282.77 229.23-512 512-512s512 229.23 512 512z"
],
"attrs": [
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-circle"
],
"colorPermutations": {
"12552552551": [
{}
]
}
},
{
"id": 105,
"paths": [
@@ -3820,32 +3784,6 @@
{}
]
}
},
{
"id": 170,
"paths": [
"M78 395.44c14-41.44 37.48-100.8 69.2-148.36 38.62-57.78 82.38-87.080 130.14-87.080s91.5 29.3 130 87.080c31.72 47.56 55.14 106.92 69.2 148.36 30.88 90.96 63.12 134.98 78 146.54 14.94-11.56 47.2-55.58 78-146.54 14-41.44 37.48-100.8 69.22-148.36q27.8-41.7 59.12-63.5c-75.7-111.377-201.81-183.58-344.783-183.58-0.034 0-0.068 0-0.103 0l0.006-0c-229.76 0-416 186.24-416 416-0 0.071-0 0.156-0 0.24 0 39.119 5.396 76.977 15.484 112.871l-0.704-2.931c16.78-21.74 40.4-63.34 63.22-130.74z",
"M754 436.56c-14 41.44-37.48 100.8-69.2 148.36-38.56 57.78-82.32 87.080-130 87.080s-91.5-29.3-130-87.080c-31.72-47.56-55.14-106.92-69.2-148.36-30.88-90.96-63.14-134.98-78-146.54-14.94 11.56-47.2 55.58-78 146.54-14.38 41.44-37.8 100.8-69.6 148.36q-27.8 41.7-59.12 63.5c75.7 111.378 201.81 183.58 344.783 183.58 0.119 0 0.237-0 0.356-0l-0.019 0c229.76 0 416-186.24 416-416 0-0.071 0-0.156 0-0.24 0-39.119-5.396-76.977-15.484-112.871l0.704 2.931c-16.78 21.74-40.4 63.34-63.22 130.74z",
"M921.56 334.62c4.098 24.449 6.44 52.617 6.44 81.332 0 0.017-0 0.034-0 0.051l0-0.003c0 0.095 0 0.208 0 0.32 0 282.593-229.087 511.68-511.68 511.68-0.113 0-0.225-0-0.338-0l0.018 0c-0.014 0-0.031 0-0.048 0-28.716 0-56.884-2.342-84.325-6.845l2.993 0.405c72.483 63.623 168.109 102.44 272.802 102.44 0.203 0 0.406-0 0.61-0l-0.031 0c229.76 0 416-186.24 416-416 0-0.172 0-0.375 0-0.578 0-104.692-38.817-200.319-102.844-273.271l0.404 0.47z"
],
"attrs": [
{},
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-telemetry-aggregate"
],
"colorPermutations": {
"12552552551": [
{},
{},
{}
]
}
}
],
"invisible": false,

View File

@@ -53,7 +53,6 @@
<glyph unicode="&#xe92b;" glyph-name="icon-eye-disabled" d="M209.46 223.32q-7.46 9.86-14.26 20.28c-14.737 21.984-27.741 47.184-37.759 73.847l-0.841 2.553c11.078 29.259 24.068 54.443 39.51 77.869l-0.91-1.469c23.221 34.963 50.705 64.8 82.207 89.793l0.793 0.607c57.663 45.719 130.179 75.053 209.311 79.947l1.069 0.053 114.48 140.88c-27.366 5.017-58.869 7.898-91.041 7.92h-0.019c-245.8 0-452.2-168-510.8-395.6 21.856-82.93 60.906-154.847 113.325-214.773l-0.525 0.613zM814.76 416.92q7.52-10 14.44-20.52c14.737-21.984 27.741-47.184 37.759-73.847l0.841-2.553c-10.859-29.216-23.863-54.416-39.447-77.748l0.847 1.348c-23.221-34.963-50.705-64.8-82.207-89.793l-0.793-0.607c-57.762-45.834-130.437-75.216-209.743-80.049l-1.057-0.051-114.46-140.86c27.346-4.988 58.817-7.84 90.955-7.84 0.037 0 0.074 0 0.111 0h-0.005c245.8 0 452.2 168 510.8 395.6-21.856 82.93-60.906 154.847-113.325 214.773l0.525-0.613zM832 832l-832-1024h192l832 1024h-192z" />
<glyph unicode="&#xe92c;" glyph-name="icon-notebook-page" d="M830 770h-830l-4-702c0-106.6 87.4-194 194-194h640c106.6 0 194 87.4 194 194v508c0 106.8-87.4 194-194 194zM832 386l-384-384-192 192v256l192-192 384 384v-256z" />
<glyph unicode="&#xe92d;" glyph-name="icon-unlocked" d="M768 832c-141.339-0.114-255.886-114.661-256-255.989v-128.011h-448c-35.301-0.113-63.887-28.699-64-63.989v-512.011c0.113-35.301 28.699-63.887 63.989-64h638.011c35.301 0.113 63.887 28.699 64 63.989v512.011c-0.113 35.301-28.699 63.887-63.989 64h-62.011v128c0 70.692 57.308 128 128 128s128-57.308 128-128v0-128h128v128c-0.114 141.339-114.661 255.886-255.989 256h-0.011z" />
<glyph unicode="&#xe92e;" glyph-name="icon-circle" d="M1024 320c0-282.77-229.23-512-512-512s-512 229.23-512 512c0 282.77 229.23 512 512 512s512-229.23 512-512z" />
<glyph unicode="&#xea00;" glyph-name="icon-arrows-right-left" d="M1024 320l-448-512v1024zM448 832l-448-512 448-512z" />
<glyph unicode="&#xea01;" glyph-name="icon-arrows-up-down" d="M512 832l512-448h-1024zM0 256l512-448 512 448z" />
<glyph unicode="&#xea02;" glyph-name="icon-bullet" d="M832 80c0-44-36-80-80-80h-480c-44 0-80 36-80 80v480c0 44 36 80 80 80h480c44 0 80-36 80-80v-480z" />
@@ -157,5 +156,4 @@
<glyph unicode="&#xeb28;" glyph-name="icon-condition-widget" d="M832 832h-640c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM512 64l-384 256 384 256 384-256z" />
<glyph unicode="&#xeb29;" glyph-name="icon-alphanumeric" d="M535.6 301.4c-8.4-1.6-17.2-3-26.2-4s-18.2-2.4-27.2-4c-10.196-1.861-18.808-4.010-27.21-6.633l1.61 0.433c-8.609-2.674-16.105-6.348-22.89-10.987l0.29 0.187c-6.693-4.517-12.283-10.107-16.663-16.585l-0.137-0.215c-4.6-6.8-7.4-15.6-8.8-26s-0.4-18.4 2.4-25.2c2.746-6.688 7.224-12.195 12.881-16.122l0.119-0.078c5.967-4.053 13.057-6.94 20.704-8.161l0.296-0.039c7.592-1.527 16.319-2.4 25.25-2.4 0.123 0 0.246 0 0.369 0h-0.019c22.2 0 39.6 3.6 52.6 11s23.2 16.2 30.2 26.4c6.273 8.873 11.271 19.191 14.426 30.285l0.174 0.715c1.853 6.809 3.601 15.41 4.855 24.169l0.145 1.231 5.2 41.6c-5.4-4.217-11.723-7.564-18.583-9.689l-0.417-0.111c-6.489-2.241-14.362-4.255-22.444-5.662l-0.956-0.138zM1024 448v192h-152l24 192h-192l-24-192h-256l24 192h-192l-24-192h-232v-192h208l-32-256h-176v-192h152l-24-192h192l24 192h256l-24-192h192l24 192h232v192h-208l32 256zM702.8 420.2l-26.4-211.8c-2.231-15.809-3.537-34.122-3.6-52.727v-0.073c0-16.8 2.2-29.4 6.4-37.8h-113.4c-1.342 5.556-2.338 12.122-2.781 18.84l-0.019 0.36c-0.261 3.524-0.409 7.634-0.409 11.778 0 2.962 0.076 5.907 0.226 8.832l-0.017-0.41c-18.663-17.401-41.395-30.694-66.597-38.289l-1.203-0.311c-22.627-6.956-48.639-10.974-75.586-11h-0.014c-0.764-0.011-1.666-0.018-2.569-0.018-18.098 0-35.598 2.563-52.156 7.345l1.325-0.328c-15.991 4.512-29.851 12.090-41.545 22.122l0.145-0.122c-11.233 9.982-19.792 22.733-24.624 37.192l-0.176 0.608c-5.2 15.2-6.4 33.4-3.8 54.4s9.4 42.2 19.4 57.2c9.524 14.399 21.535 26.346 35.532 35.512l0.468 0.288c13.387 8.662 28.922 15.533 45.512 19.765l1.088 0.235c13.436 3.792 30.801 7.554 48.47 10.41l2.93 0.39c17 2.6 33.8 4.6 50.4 6.2 16.628 1.527 31.69 4.070 46.349 7.643l-2.149-0.443c13 3 23.6 7.6 31.6 13.6s12.6 15 13.6 26.4 0.8 21.8-2.4 28.8c-2.849 6.902-7.542 12.56-13.468 16.517l-0.132 0.083c-6.217 4.011-13.604 6.78-21.543 7.774l-0.257 0.026c-7.897 1.277-17 2.007-26.274 2.007-0.537 0-1.073-0.002-1.609-0.007l0.082 0.001c-22 0-40-4.6-53.8-14.2s-23-25.2-28-47.2h-111.8c4.8 26.2 14.2 48 27.8 65.4 13.475 16.978 29.89 30.968 48.574 41.377l0.826 0.423c18.192 10.038 39.297 17.806 61.619 22.175l1.381 0.225c20.488 4.162 44.053 6.563 68.171 6.6h0.029c21.8-0.005 43.239-1.532 64.222-4.479l-2.422 0.279c20.641-2.809 39.324-8.783 56.401-17.461l-1.001 0.461c15.909-8.108 28.858-20.031 37.967-34.601l0.233-0.399c9-15 12.2-34.8 9-59.6z" />
<glyph unicode="&#xeb2a;" glyph-name="icon-image-telemetry" d="M512 832c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM783.6 48.4c-69.581-69.675-165.757-112.776-272-112.776-212.298 0-384.4 172.102-384.4 384.4s172.102 384.4 384.4 384.4c212.298 0 384.4-172.102 384.4-384.4 0-0.008 0-0.017 0-0.025v0.001c0.001-0.264 0.001-0.575 0.001-0.887 0-105.769-42.964-201.503-112.391-270.703l-0.010-0.010zM704 448l-128-128-192 192-192-192c0-176.731 143.269-320 320-320s320 143.269 320 320v0z" />
<glyph unicode="&#xeb2b;" glyph-name="icon-telemetry-aggregate" d="M78 436.56c14 41.44 37.48 100.8 69.2 148.36 38.62 57.78 82.38 87.080 130.14 87.080s91.5-29.3 130-87.080c31.72-47.56 55.14-106.92 69.2-148.36 30.88-90.96 63.12-134.98 78-146.54 14.94 11.56 47.2 55.58 78 146.54 14 41.44 37.48 100.8 69.22 148.36q27.8 41.7 59.12 63.5c-75.7 111.377-201.81 183.58-344.783 183.58-0.034 0-0.068 0-0.103 0h0.006c-229.76 0-416-186.24-416-416 0-0.071 0-0.156 0-0.24 0-39.119 5.396-76.977 15.484-112.871l-0.704 2.931c16.78 21.74 40.4 63.34 63.22 130.74zM754 395.44c-14-41.44-37.48-100.8-69.2-148.36-38.56-57.78-82.32-87.080-130-87.080s-91.5 29.3-130 87.080c-31.72 47.56-55.14 106.92-69.2 148.36-30.88 90.96-63.14 134.98-78 146.54-14.94-11.56-47.2-55.58-78-146.54-14.38-41.44-37.8-100.8-69.6-148.36q-27.8-41.7-59.12-63.5c75.7-111.378 201.81-183.58 344.783-183.58 0.119 0 0.237 0 0.356 0h-0.019c229.76 0 416 186.24 416 416 0 0.071 0 0.156 0 0.24 0 39.119-5.396 76.977-15.484 112.871l0.704-2.931c-16.78-21.74-40.4-63.34-63.22-130.74zM921.56 497.38c4.098-24.449 6.44-52.617 6.44-81.332 0-0.017 0-0.034 0-0.051v0.003c0-0.095 0-0.208 0-0.32 0-282.593-229.087-511.68-511.68-511.68-0.113 0-0.225 0-0.338 0h0.018c-0.014 0-0.031 0-0.048 0-28.716 0-56.884 2.342-84.325 6.845l2.993-0.405c72.483-63.623 168.109-102.44 272.802-102.44 0.203 0 0.406 0 0.61 0h-0.031c229.76 0 416 186.24 416 416 0 0.172 0 0.375 0 0.578 0 104.692-38.817 200.319-102.844 273.271l0.404-0.47z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -39,7 +39,13 @@ export function paramsToArray(openmct) {
}
export function identifierToString(openmct, objectPath) {
return '#/browse/' + openmct.objects.getRelativePath(objectPath);
let identifier = '#/browse/' + objectPath.map(function (o) {
return o && openmct.objects.makeKeyString(o.identifier);
})
.reverse()
.join('/');
return identifier;
}
export default function objectPathToUrl(openmct, objectPath) {

View File

@@ -21,7 +21,7 @@
*****************************************************************************/
<template>
<div
class="c-so-view js-notebook-snapshot-item-wrapper"
class="c-so-view"
:class="[
statusClass,
'c-so-view--' + domainObject.type,
@@ -56,11 +56,6 @@
'has-complex-content': complexContent
}"
>
<NotebookMenuSwitcher v-if="notebookEnabled"
:domain-object="domainObject"
:object-path="objectPath"
class="c-notebook-snapshot-menubutton"
/>
<div v-if="statusBarItems.length > 0"
class="c-so-view__frame-controls__btns"
>
@@ -85,7 +80,7 @@
<object-view
ref="objectView"
class="c-so-view__object-view js-object-view js-notebook-snapshot-item"
class="c-so-view__object-view js-object-view"
:show-edit-view="showEditView"
:object-path="objectPath"
:layout-font-size="layoutFontSize"
@@ -97,7 +92,6 @@
<script>
import ObjectView from './ObjectView.vue';
import NotebookMenuSwitcher from '@/plugins/notebook/components/NotebookMenuSwitcher.vue';
const SIMPLE_CONTENT_TYPES = [
'clock',
@@ -109,8 +103,7 @@ const SIMPLE_CONTENT_TYPES = [
export default {
components: {
ObjectView,
NotebookMenuSwitcher
ObjectView
},
inject: ['openmct'],
props: {
@@ -146,7 +139,6 @@ export default {
return {
cssClass,
complexContent,
notebookEnabled: this.openmct.types.get('notebook'),
statusBarItems: [],
status: ''
};

View File

@@ -1,3 +1,25 @@
/*****************************************************************************
* 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>
<li
draggable="true"

View File

@@ -1,3 +1,25 @@
/*****************************************************************************
* 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-elements-pool">
<Search

View File

@@ -1,3 +1,25 @@
/*****************************************************************************
* 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">
<object-name />
@@ -19,7 +41,9 @@
type="vertical"
>
<pane class="c-inspector__properties">
<properties />
<Properties
v-if="!activity"
/>
<location />
<inspector-views />
</pane>
@@ -57,7 +81,7 @@ import multipane from '../layout/multipane.vue';
import pane from '../layout/pane.vue';
import ElementsPool from './ElementsPool.vue';
import Location from './Location.vue';
import Properties from './Properties.vue';
import Properties from './details/Properties.vue';
import ObjectName from './ObjectName.vue';
import InspectorViews from './InspectorViews.vue';
import _ from "lodash";
@@ -98,7 +122,8 @@ export default {
key: '__styles',
name: 'Styles'
}],
currentTabbedView: {}
currentTabbedView: {},
activity: undefined
};
},
mounted() {
@@ -111,9 +136,12 @@ export default {
methods: {
updateInspectorViews(selection) {
this.refreshComposition(selection);
if (this.openmct.types.get('conditionSet')) {
this.refreshTabs(selection);
}
this.setActivity(selection);
},
refreshComposition(selection) {
if (selection.length > 0 && selection[0].length > 0) {
@@ -150,6 +178,12 @@ export default {
},
isCurrent(view) {
return _.isEqual(this.currentTabbedView, view);
},
setActivity(selection) {
this.activity = selection
&& selection.length
&& selection[0].length
&& selection[0][0].activity;
}
}
};

View File

@@ -1,3 +1,25 @@
/*****************************************************************************
* 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.
*****************************************************************************/
export const mockTelemetryTableSelection = [
[{
context: {

View File

@@ -1,10 +1,29 @@
/*****************************************************************************
* 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></div>
</template>
<style>
</style>
<script>
export default {
inject: ['openmct'],

View File

@@ -1,3 +1,25 @@
/*****************************************************************************
* 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-inspect-properties c-inspect-properties--location">
<div

View File

@@ -1,3 +1,25 @@
/*****************************************************************************
* 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__header">
<div v-if="!multiSelect"

View File

@@ -1,171 +0,0 @@
<template>
<div v-if="!activity"
class="c-inspector__properties c-inspect-properties"
>
<div class="c-inspect-properties__header">
Details
</div>
<ul
v-if="!multiSelect && !singleSelectNonObject"
class="c-inspect-properties__section"
>
<li class="c-inspect-properties__row">
<div class="c-inspect-properties__label">
Title
</div>
<div class="c-inspect-properties__value">
{{ item.name }}
</div>
</li>
<li class="c-inspect-properties__row">
<div class="c-inspect-properties__label">
Type
</div>
<div class="c-inspect-properties__value">
{{ typeName }}
</div>
</li>
<li
v-if="item.created"
class="c-inspect-properties__row"
>
<div class="c-inspect-properties__label">
Created
</div>
<div class="c-inspect-properties__value">
{{ formatTime(item.created) }}
</div>
</li>
<li
v-if="item.modified"
class="c-inspect-properties__row"
>
<div class="c-inspect-properties__label">
Modified
</div>
<div class="c-inspect-properties__value">
{{ formatTime(item.modified) }}
</div>
</li>
<li
v-for="prop in typeProperties"
:key="prop.name"
class="c-inspect-properties__row"
>
<div class="c-inspect-properties__label">
{{ prop.name }}
</div>
<div class="c-inspect-properties__value">
{{ prop.value }}
</div>
</li>
</ul>
<div
v-if="multiSelect"
class="c-inspect-properties__row--span-all"
>
No properties to display for multiple items
</div>
<div
v-if="singleSelectNonObject"
class="c-inspect-properties__row--span-all"
>
No properties to display for this item
</div>
</div>
</template>
<script>
import Moment from "moment";
export default {
inject: ['openmct'],
data() {
return {
domainObject: {},
activity: undefined,
multiSelect: false
};
},
computed: {
item() {
return this.domainObject || {};
},
type() {
return this.openmct.types.get(this.item.type);
},
typeName() {
if (!this.type) {
return `Unknown: ${this.item.type}`;
}
return this.type.definition.name;
},
typeProperties() {
if (!this.type) {
return [];
}
let definition = this.type.definition;
if (!definition.form || definition.form.length === 0) {
return [];
}
return definition.form
.map((field) => {
let path = field.property;
if (typeof path === 'string') {
path = [path];
}
return {
name: field.name,
path
};
})
.filter(field => Array.isArray(field.path))
.map((field) => {
return {
name: field.name,
value: field.path.reduce((object, key) => {
return object[key];
}, this.item)
};
});
},
singleSelectNonObject() {
return !this.item.identifier && !this.multiSelect;
}
},
mounted() {
this.openmct.selection.on('change', this.updateSelection);
this.updateSelection(this.openmct.selection.get());
},
beforeDestroy() {
this.openmct.selection.off('change', this.updateSelection);
},
methods: {
updateSelection(selection) {
if (selection.length === 0 || selection[0].length === 0) {
this.domainObject = {};
return;
}
if (selection.length > 1) {
this.multiSelect = true;
this.domainObject = {};
return;
} else {
this.multiSelect = false;
this.domainObject = selection[0][0].context.item;
this.activity = selection[0][0].context.activity;
}
},
formatTime(unixTime) {
return Moment.utc(unixTime).format('YYYY-MM-DD[\n]HH:mm:ss') + ' UTC';
}
}
};
</script>

View File

@@ -19,14 +19,25 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import Agent from "../../utils/agent/Agent";
import DeviceClassifier from "./src/DeviceClassifier";
export default () => {
return (openmct) => {
openmct.on("start", () => {
const agent = new Agent(window);
DeviceClassifier(agent, window.document);
});
};
<template>
<li class="c-inspect-properties__row">
<div class="c-inspect-properties__label">
{{ detail.name }}
</div>
<div class="c-inspect-properties__value">
{{ detail.value }}
</div>
</li>
</template>
<script>
export default {
props: {
detail: {
type: Object,
required: true
}
}
};
</script>

View File

@@ -20,38 +20,31 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* An object containing key-value pairs, where keys are symbolic of
* device attributes, and values are functions that take the
* `agent` as inputs and return boolean values indicating
* whether or not the current device has these attributes.
*
* For internal use by the mobile support bundle.
*
* @memberof src/plugins/DeviceClassifier
* @private
*/
<template>
<li class="c-inspect-properties__row">
<div class="c-inspect-properties__label">
{{ detail.name }}
</div>
<div class="c-inspect-properties__value">
{{ formattedTime }}
</div>
</li>
</template>
<script>
import Moment from 'moment';
export default {
mobile: function (agent) {
return agent.isMobile();
props: {
detail: {
type: Object,
required: true
}
},
phone: function (agent) {
return agent.isPhone();
},
tablet: function (agent) {
return agent.isTablet();
},
desktop: function (agent) {
return !agent.isMobile();
},
portrait: function (agent) {
return agent.isPortrait();
},
landscape: function (agent) {
return agent.isLandscape();
},
touch: function (agent) {
return agent.isTouch();
computed: {
formattedTime() {
return Moment.utc(this.detail.value).format('YYYY-MM-DD[\n]HH:mm:ss') + ' UTC';
}
}
};
</script>

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