Compare commits

...

16 Commits

Author SHA1 Message Date
David Tsay
0e4685bff3 reduce code 2021-06-15 15:57:03 -07:00
David Tsay
7a928989ab revert b919cf9 to be fixed properly 2021-06-15 14:51:51 -07:00
David Tsay
b919cf9f69 add mmgis (external plugin) type to style exclusion list 2021-06-15 14:08:40 -07:00
David Tsay
4b191c5e39 check if there is an element to style 2021-06-15 10:35:09 -07:00
Shefali Joshi
6483fe2402 Prepare master for Sprint 1.7.4 (#3925) 2021-06-07 11:37:49 -07:00
Shefali Joshi
a123889d6a Pre release for Sprint 1.7.3 (#3924)
* Revert "upgrade to webpack5 (#3871)" (#3907) (#3908)
* [Navigation Tree] Fix composition on closed folders and scrolling for items NOT in tree (#3920)
* Update package.json version and version documentation to include tags for npmjs

Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov>
2021-06-07 11:25:58 -07:00
Nikhil
a40867d544 Revert "upgrade to webpack5 (#3871)" (#3907)
This reverts commit e1e0eeac56.
2021-06-02 07:04:40 -07:00
Charles Hacskaylo
dbed9262c0 Tree revert refactor (#3886)
* Reverts object tree to expand/collapse tree model
* Retains expanded/collapsed state 
* Adds collapse all feature
2021-06-01 15:47:21 -07:00
Henry Hsu
43ac66233e [Issue] remove FollowTimerAction, followIndicator and tests (#3855)
Co-authored-by: Henry Hsu <henryhsu@Henrys-MacBook-Air.local>
Co-authored-by: Andrew Henry <akhenry@gmail.com>
2021-05-28 16:06:09 -07:00
Andrew Henry
04e85c176a Update templates (#3904) 2021-05-28 14:55:36 -07:00
Shefali Joshi
8274c23129 Plots limit lines (#3882) 2021-05-28 14:51:29 -07:00
John Hill
5fafde5f23 Updates to recognize issue template config (#3902)
* issue template config

* Update PR Template

Co-authored-by: unlikelyzero <jchill2@gmail.com>
Co-authored-by: Andrew Henry <akhenry@gmail.com>
2021-05-28 14:16:56 -07:00
Charles Hacskaylo
80a6e7f719 Fix erroneously checked in dev code (#3897)
Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
2021-05-28 13:22:11 -07:00
Shefali Joshi
2c13aeecce Make legend configuration properties reactive (#3889)
Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
2021-05-28 13:13:57 -07:00
Shefali Joshi
ac015c3e45 Updates to the sprint cycle and end of sprint release process (#3878)
* Updates to the sprint cycle and end of sprint release process

* Adds reviewer checklist item for labelling an issue as a bug

* Update Cycle doc with test process changes.

* Update static.md references, add Issue templates

* Updated criticality definition

Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov>
Co-authored-by: John Hill <jchill2.spam@gmail.com>
Co-authored-by: Andrew Henry <akhenry@gmail.com>
2021-05-28 12:24:14 -07:00
Shefali Joshi
ae1a4bcc6a A change in the parent container's size for plots re-requests telemetry (#3890)
* Use resize obeserver to detect a change in the parent container's size for plots and re-request telemetry
2021-05-28 11:44:56 -07:00
56 changed files with 1398 additions and 9685 deletions

43
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,43 @@
<!--- This is for filing bugs. If you have a general question, please -->
<!--- visit https://github.com/nasa/openmct/discussions -->
---
name: Bug Report
about: File a Bug !
---
<!--- Focus on user impact in the title. Use the Summary Field to -->
<!--- describe the problem technically. -->
#### Summary
<!--- A description of the issue encountered. When possible, a description -->
<!--- of the impact of the issue. What use case does it impede?-->
#### Expected vs Current Behavior
<!--- Tell us what should have happened -->
#### Impact Check List
<!--- Please select from the following options -->
- [ ] Data loss or misrepresented data?
- [ ] Regression? Did this used to work or has it always been broken?
- [ ] Is there a workaround available?
- [ ] Does this impact a critical component?
- [ ] Is this just a visual bug?
#### Steps to Reproduce
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. Include code to reproduce, if relevant -->
1.
2.
3.
4.
#### Environment
* Open MCT Version: <!--- date of build, version, or SHA -->
* Deployment Type: <!--- npm dev? VIPER Dev? openmct-yams? -->
* OS:
* Browser:
#### Additional Information
<!--- Include any screenshots, gifs, or logs which will expedite triage -->

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -0,0 +1,23 @@
<!--- This is for filing enhancements or features. If you have a general -->
<!--- question, please visit https://github.com/nasa/openmct/discussions -->
---
name: Feature Request
about: Suggest an idea for this project
---
<!--
Thank you for suggesting an idea to make Open MCT better.
Please fill in as much of the template below as you're able.
-->
**Is your feature request related to a problem? Please describe.**
<!-- Please describe the problem you are trying to solve. -->
**Describe the solution you'd like**
<!--- Please describe the desired behavior. -->
**Describe alternatives you've considered**
<!--- Please describe alternative solutions or features you have considered. -->

12
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,12 @@
### All Submissions:
* [ ] Have you followed the guidelines in our [Contributing document](https://github.com/nasa/openmct/blob/master/CONTRIBUTING.md)?
* [ ] Have you checked to ensure there aren't other open [Pull Requests](https://github.com/nasa/openmct/pulls) for the same update/change?
### Author Checklist
* [ ] Changes address original issue?
* [ ] Unit tests included and/or updated with changes?
* [ ] Command line build passes?
* [ ] Has this been smoke tested?
* [ ] Testing instructions included in associated issue?

2
.gitignore vendored
View File

@@ -39,3 +39,5 @@ npm-debug.log
# karma reports
report.*.json
package-lock.json

View File

@@ -10,7 +10,7 @@ accept changes from external contributors.
The short version:
1. Write your contribution.
1. Write your contribution or describe your idea in the form of an [GitHub issue](https://github.com/nasa/openmct/issues/new/choose) or [Starting a GitHub Discussion](https://github.com/nasa/openmct/discussions)
2. Make sure your contribution meets code, test, and commit message
standards as described below.
3. Submit a pull request from a topic branch back to `master`. Include a check
@@ -18,6 +18,7 @@ The short version:
for review.)
4. Respond to any discussion. When the reviewer decides it's ready, they
will merge back `master` and fill out their own check list.
5. If you are a first-time contributor, please see [this discussion](https://github.com/nasa/openmct/discussions/3821) for further information.
## Contribution Process
@@ -115,7 +116,7 @@ the pull request containing the reviewer checklist (from below) and complete
the merge back to the master branch.
Additionally:
* Every pull request must link to the issue that it addresses. Eg. “Addresses #1234” or “Closes #1234”. This is the responsibility of the pull requests __author__. If no issue exists, create one.
* Every pull request must link to the issue that it addresses. Eg. “Addresses #1234” or “Closes #1234”. This is the responsibility of the pull requests __author__. If no issue exists, [create one](https://github.com/nasa/openmct/issues/new/choose).
* Every __author__ must include testing instructions. These instructions should identify the areas of code affected, and some minimal test steps. If addressing a bug, reproduction steps should be included, if they were not included in the original issue. If reproduction steps were included on the original issue, and are sufficient, refer to them.
* A pull request that closes an issue should say so in the description. Including the text “Closes #1234” will cause the linked issue to be automatically closed when the pull request is merged. This is the responsibility of the pull requests __author__.
* When a pull request is merged, and the corresponding issue closed, the __reviewer__ must add the tag “unverified” to the original issue. This will indicate that although the issue is closed, it has not been tested yet.
@@ -296,23 +297,12 @@ these standards.
Issues are tracked at https://github.com/nasa/openmct/issues.
Issues should include:
* A short description of the issue encountered.
* A longer-form description of the issue encountered. When possible, steps to
reproduce the issue.
* When possible, a description of the impact of the issue. What use case does
it impede?
* An assessment of the severity of the issue.
Issue severity is categorized as follows (in ascending order):
* _Trivial_: Minimal impact on the usefulness and functionality of the
software; a "nice-to-have."
* _(Unspecified)_: Major loss of functionality or impairment of use.
* _Critical_: Large-scale loss of functionality or impairment of use,
such that remaining utility becomes marginal.
* _Blocker_: Harmful or otherwise unacceptable behavior. Must fix.
* _Trivial_: Minimal impact on the usefulness and functionality of the software; a "nice-to-have." Visual impact without functional impact,
* _Medium_: Some impairment of use, but simple workarounds exist
* _Critical_: Significant loss of functionality or impairment of use. Display of telemetry data is not affected though.
* _Blocker_: Major functionality is impaired or lost, threatening mission success. Display of telemetry data is impaired or blocked by the bug, which could lead to loss of situational awareness.
## Check Lists
@@ -322,16 +312,19 @@ checklist).
### Author Checklist
1. Changes address original issue?
2. Unit tests included and/or updated with changes?
3. Command line build passes?
4. Changes have been smoke-tested?
5. Testing instructions included?
[Within PR Template](.github/PULL_REQUEST_TEMPLATE.md)
### Reviewer Checklist
1. Changes appear to address issue?
2. Appropriate unit tests included?
3. Code style and in-line documentation are appropriate?
4. Commit messages meet standards?
5. Has associated issue been labelled `unverified`? (only applicable if this PR closes the issue)
* [ ] Changes appear to address issue?
* [ ] Appropriate unit tests included?
* [ ] Code style and in-line documentation are appropriate?
* [ ] Commit messages meet standards?
* [ ] Has associated issue been labelled `unverified`? (only applicable if this PR closes the issue)
* [ ] Has associated issue been labelled `bug`? (only applicable if this PR is for a bug fix)
* [ ] List of Acceptance Tests Performed.
Write out a small list of tests performed with just enough detail for another developer on the team
to execute.
i.e. ```When Clicking on Add button, new `object` appears in dropdown.```

View File

@@ -44,7 +44,7 @@ The clearest examples for developing Open MCT plugins are in the
our documentation.
We want Open MCT to be as easy to use, install, run, and develop for as
possible, and your feedback will help us get there! Feedback can be provided via [GitHub issues](https://github.com/nasa/openmct/issues), or by emailing us at [arc-dl-openmct@mail.nasa.gov](mailto:arc-dl-openmct@mail.nasa.gov).
possible, and your feedback will help us get there! Feedback can be provided via [GitHub issues](https://github.com/nasa/openmct/issues/new/choose), [Starting a GitHub Discussion](https://github.com/nasa/openmct/discussions), or by emailing us at [arc-dl-openmct@mail.nasa.gov](mailto:arc-dl-openmct@mail.nasa.gov).
## Building Applications With Open MCT

10
app.js
View File

@@ -7,14 +7,6 @@
* node app.js [options]
*/
class WatchRunPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('WatchRunPlugin', (compilation, callback) => {
console.log('Begin compile at ' + new Date());
callback();
});
}
}
const options = require('minimist')(process.argv.slice(2));
const express = require('express');
@@ -51,7 +43,7 @@ app.use('/proxyUrl', function proxyRequest(req, res, next) {
const webpack = require('webpack');
const webpackConfig = require('./webpack.config.js');
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
webpackConfig.plugins.push(new WatchRunPlugin());
webpackConfig.plugins.push(function() { this.plugin('watch-run', function(watching, callback) { console.log('Begin compile at ' + new Date()); callback(); }) });
webpackConfig.entry.openmct = [
'webpack-hot-middleware/client?reload=true',

View File

@@ -73,11 +73,11 @@ acceptance testing (e.g. by resolving any blockers found); any
resources not needed for this effort should be used to begin work
for the subsequent sprint.
| Week | Mon | Tue | Wed | Thu | Fri |
|:-----:|:-------------------------:|:------:|:---:|:----------------------------:|:-----------:|
| __1__ | Sprint plan | Tag-up | | | |
| __2__ | | Tag-up | | | Code freeze |
| __3__ | Per-sprint testing | Triage | | _Per-sprint testing*_ | Ship |
| Week | Mon | Tue | Wed | Thu | Fri |
|:-----:|:-------------------------:|:------:|:---:|:----------------------------:|:-------------------------------------:|
| __1__ | Sprint plan | Tag-up | | | |
| __2__ | | Tag-up | | | Code freeze and sprint branch |
| __3__ | Per-sprint testing | Triage | | _Per-sprint testing*_ | Ship and merge sprint branch to master|
&ast; If necessary.
@@ -105,14 +105,20 @@ emphasis on testing.
that team may begin work for that sprint during the
third week, since testing and blocker resolution is unlikely
to require all available resources.
* Testing success criteria identified per issue (where necessary). This could be in the form of acceptance tests on the issue or detailing performance tests, for example.
* __Tag-up.__ Check in and status update among development team.
May amend plan for sprint as-needed.
* __Code freeze.__ Any new work from this sprint
(features, bug fixes, enhancements) must be integrated by the
end of the second week of the sprint. After code freeze
(and until the end of the sprint) the only changes that should be
merged into the master branch should directly address issues
needed to pass acceptance testing.
end of the second week of the sprint. After code freeze, a sprint
branch will be created (and until the end of the sprint) the only
changes that should be merged into the sprint branch should
directly address issues needed to pass acceptance testing.
During this time, any other feature development will continue to
be merged into the master branch for the next sprint.
* __Sprint branch merge to master.__ After acceptance testing, the sprint branch
will be merged back to the master branch. Any code conflicts that
arise will be resolved by the team.
* [__Per-release Testing.__](testing/plan.md#per-release-testing)
Structured testing with predefined
success criteria. No release should ship without passing
@@ -126,8 +132,8 @@ emphasis on testing.
* [__Testathon.__](testing/plan.md#user-testing)
Multi-user testing, involving as many users as
is feasible, plus development team. Open-ended; should verify
completed work from this sprint, test exploratorily for
regressions, et cetera.
completed work from this sprint using the sprint branch, test
exploratorily for regressions, et cetera.
* [__Long-Duration Test.__](testing/plan.md#long-duration-testing) A
test to verify that the software remains
stable after running for longer durations. May include some
@@ -143,7 +149,7 @@ emphasis on testing.
Subset of Pre-release Testing
which should be performed before shipping at the end of any
sprint. Time is allocated for a second round of
Pre-release Testing if the first round is not passed.
Pre-release Testing if the first round is not passed. Smoke tests collected from issues/PRs
* __Triage.__ Team reviews issues from acceptance testing and uses
success criteria to determine whether or not they should block
release, then formulates a plan to address these issues before

View File

@@ -19,7 +19,7 @@ Testing for Open MCT includes:
Manual, non-rigorous testing of the software and/or specific features
of interest. Verifies that the software runs and that basic functionality
is present.
is present. The outcome of Smoke Testing should be a simplified list of Acceptance Tests which could be executed by another team member with sufficient context.
### Unit Testing
@@ -49,7 +49,7 @@ User testing will focus on the following activities:
* General "trying to break things."
During user testing, users will
[report issues](https://github.com/nasa/openmctweb/blob/master/CONTRIBUTING.md#issue-reporting)
[report issues](https://github.com/nasa/openmct/issues/new/choose)
as they are encountered.
Desired outcomes of user testing are:
@@ -71,7 +71,7 @@ usage. After twenty-four hours, the software is evaluated for:
at the start of the test? Is it as responsive?
Any defects or unexpected behavior identified during testing should be
[reported as issues](https://github.com/nasa/openmctweb/blob/master/CONTRIBUTING.md#issue-reporting)
[reported as issues](https://github.com/nasa/openmct/issues/new/choose)
and reviewed for severity.
## Test Performance

View File

@@ -92,8 +92,8 @@ should update (or delegate the task of updating) Open MCT version
numbers by the following process:
1. Update version number in `package.json`
1. Create a new branch off the `master` branch.
2. Remove `-SNAPSHOT` suffix from the version in `package.json`.
1. Checkout branch created for the last sprint that has been successfully tested.
2. Remove a `-SNAPSHOT` suffix from the version in `package.json`.
3. Verify that resulting version number meets semantic versioning
requirements relative to previous stable version. Increment the
version number if necessary.
@@ -131,7 +131,8 @@ numbers by the following process:
3. In `package.json` change package to be public (private: false)
4. Test the package before publishing by doing `npm publish --dry-run`
if necessary.
5. Publish the package to the npmjs registry (e.g. `npm publish --access public`)
5. Publish the package to the npmjs registry (e.g. `npm publish --access public`)
NOTE: Use the `--tag unstable` flag to the npm publishj if this is a prerelease.
6. Confirm the package has been published (e.g. `https://www.npmjs.com/package/openmct`)
5. Update snapshot status in `package.json`
1. Create a new branch off the `master` branch.

View File

@@ -93,5 +93,36 @@ define([
};
};
SinewaveLimitProvider.prototype.getLimits = function (domainObject) {
return {
limits: function () {
return {
WARNING: {
low: {
cssClass: "is-limit--lwr is-limit--yellow",
sin: -YELLOW.sin,
cos: -YELLOW.cos
},
high: {
cssClass: "is-limit--upr is-limit--yellow",
...YELLOW
}
},
DISTRESS: {
low: {
cssClass: "is-limit--lwr is-limit--red",
sin: -RED.sin,
cos: -RED.cos
},
high: {
cssClass: "is-limit--upr is-limit--red",
...RED
}
}
};
}
};
};
return SinewaveLimitProvider;
});

8613
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "openmct",
"version": "1.7.3-SNAPSHOT",
"version": "1.7.4-SNAPSHOT",
"description": "The Open MCT core platform",
"dependencies": {},
"devDependencies": {
@@ -9,7 +9,7 @@
"babel-eslint": "10.0.3",
"comma-separated-values": "^3.6.4",
"concurrently": "^3.6.1",
"copy-webpack-plugin": "^9.0.0",
"copy-webpack-plugin": "^4.5.2",
"cross-env": "^6.0.3",
"css-loader": "^1.0.0",
"d3-array": "1.2.x",
@@ -41,19 +41,19 @@
"jsdoc": "^3.3.2",
"karma": "5.1.1",
"karma-chrome-launcher": "3.1.0",
"karma-firefox-launcher": "1.3.0",
"karma-cli": "2.0.0",
"karma-coverage": "2.0.3",
"karma-coverage-istanbul-reporter": "3.0.3",
"karma-firefox-launcher": "1.3.0",
"karma-html-reporter": "0.2.7",
"karma-jasmine": "3.3.1",
"karma-sourcemap-loader": "0.3.7",
"karma-webpack": "^5.0.0",
"karma-webpack": "4.0.2",
"location-bar": "^3.0.1",
"lodash": "^4.17.12",
"markdown-toc": "^0.11.7",
"marked": "^0.3.5",
"mini-css-extract-plugin": "^1.6.0",
"mini-css-extract-plugin": "^0.4.1",
"minimist": "^1.2.5",
"moment": "2.25.3",
"moment-duration-format": "^2.2.2",
@@ -69,10 +69,10 @@
"uuid": "^3.3.3",
"v8-compile-cache": "^1.1.0",
"vue": "2.5.6",
"vue-loader": "^15.9.7",
"vue-loader": "^15.2.6",
"vue-template-compiler": "2.5.6",
"webpack": "^5.37.0",
"webpack-cli": "^3.3.12",
"webpack": "^4.16.2",
"webpack-cli": "^3.1.0",
"webpack-dev-middleware": "^3.1.3",
"webpack-hot-middleware": "^2.22.3",
"zepto": "^1.2.0"

View File

@@ -23,13 +23,11 @@
define([
"moment-timezone",
"./src/indicators/ClockIndicator",
"./src/indicators/FollowIndicator",
"./src/services/TickerService",
"./src/services/TimerService",
"./src/controllers/ClockController",
"./src/controllers/TimerController",
"./src/controllers/RefreshingController",
"./src/actions/FollowTimerAction",
"./src/actions/StartTimerAction",
"./src/actions/RestartTimerAction",
"./src/actions/StopTimerAction",
@@ -39,13 +37,11 @@ define([
], function (
MomentTimezone,
ClockIndicator,
FollowIndicator,
TickerService,
TimerService,
ClockController,
TimerController,
RefreshingController,
FollowTimerAction,
StartTimerAction,
RestartTimerAction,
StopTimerAction,
@@ -144,15 +140,6 @@ define([
}
],
"actions": [
{
"key": "timer.follow",
"implementation": FollowTimerAction,
"depends": ["timerService"],
"category": "contextual",
"name": "Follow Timer",
"cssClass": "icon-clock",
"priority": "optional"
},
{
"key": "timer.start",
"implementation": StartTimerAction,
@@ -299,10 +286,7 @@ define([
}
}
],
"runs": [{
"implementation": FollowIndicator,
"depends": ["openmct", "timerService"]
}],
"runs": [],
"licenses": [
{
"name": "moment-duration-format",

View File

@@ -1,56 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2009-2016, 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 () {
/**
* Designates a specific timer for following. Timelines, for example,
* use the actively followed timer to display a time-of-interest line
* and interpret time conductor bounds in the Timeline's relative
* time frame.
*
* @implements {Action}
* @memberof platform/features/clock
* @constructor
* @param {ActionContext} context the context for this action
*/
function FollowTimerAction(timerService, context) {
var domainObject =
context.domainObject
&& context.domainObject.useCapability('adapter');
this.perform =
timerService.setTimer.bind(timerService, domainObject);
}
FollowTimerAction.appliesTo = function (context) {
var model =
(context.domainObject && context.domainObject.getModel())
|| {};
return model.type === 'timer';
};
return FollowTimerAction;
}
);

View File

@@ -1,51 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2009-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([], function () {
/**
* Indicator that displays the active timer, as well as its
* current state.
* @memberof platform/features/clock
*/
return function installFollowIndicator(openmct, timerService) {
var indicator = openmct.indicators.simpleIndicator();
var timer = timerService.getTimer();
setIndicatorStatus(timer);
function setIndicatorStatus(newTimer) {
if (newTimer !== undefined) {
indicator.iconClass('icon-timer');
indicator.statusClass('s-status-on');
indicator.text('Following timer ' + newTimer.name);
} else {
indicator.iconClass('icon-timer');
indicator.statusClass('s-status-disabled');
indicator.text('No timer being followed');
}
}
timerService.on('change', setIndicatorStatus);
openmct.indicators.add(indicator);
};
});

View File

@@ -1,89 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2009-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
"../../src/actions/FollowTimerAction"
], function (FollowTimerAction) {
var TIMER_SERVICE_METHODS =
['setTimer', 'getTimer', 'clearTimer', 'on', 'off'];
describe("The Follow Timer action", function () {
var testContext;
var testModel;
var testAdaptedObject;
beforeEach(function () {
testModel = {};
testContext = {
domainObject: jasmine.createSpyObj('domainObject', [
'getModel',
'useCapability'
])
};
testAdaptedObject = { foo: 'bar' };
testContext.domainObject.getModel.and.returnValue(testModel);
testContext.domainObject.useCapability.and.callFake(function (c) {
return c === 'adapter' && testAdaptedObject;
});
});
it("is applicable to timers", function () {
testModel.type = "timer";
expect(FollowTimerAction.appliesTo(testContext)).toBe(true);
});
it("is inapplicable to non-timers", function () {
testModel.type = "folder";
expect(FollowTimerAction.appliesTo(testContext)).toBe(false);
});
describe("when instantiated", function () {
var mockTimerService;
var action;
beforeEach(function () {
mockTimerService = jasmine.createSpyObj(
'timerService',
TIMER_SERVICE_METHODS
);
action = new FollowTimerAction(mockTimerService, testContext);
});
it("does not interact with the timer service", function () {
TIMER_SERVICE_METHODS.forEach(function (method) {
expect(mockTimerService[method]).not.toHaveBeenCalled();
});
});
describe("and performed", function () {
beforeEach(function () {
action.perform();
});
it("sets the active timer", function () {
expect(mockTimerService.setTimer)
.toHaveBeenCalledWith(testAdaptedObject);
});
});
});
});
});

View File

@@ -1,96 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2009-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
"../../src/indicators/FollowIndicator",
"../../src/services/TimerService",
"../../../../../src/MCT",
'zepto'
], function (
FollowIndicator,
TimerService,
MCT,
$
) {
xdescribe("The timer-following indicator", function () {
var timerService;
var openmct;
beforeEach(function () {
openmct = new MCT();
timerService = new TimerService(openmct);
spyOn(openmct.indicators, "add");
});
it("adds an indicator when installed", function () {
FollowIndicator(openmct, timerService);
expect(openmct.indicators.add).toHaveBeenCalled();
});
it("indicates that no timer is being followed", function () {
FollowIndicator(openmct, timerService);
var simpleIndicator = openmct.indicators.add.calls.mostRecent().args[0];
var element = simpleIndicator.element;
var text = $('.indicator-text', element).text().trim();
expect(text).toEqual('No timer being followed');
});
describe("when a timer is set", function () {
var testObject;
var simpleIndicator;
beforeEach(function () {
testObject = {
identifier: {
namespace: 'namespace',
key: 'key'
},
name: "some timer!"
};
timerService.setTimer(testObject);
FollowIndicator(openmct, timerService);
simpleIndicator = openmct.indicators.add.calls.mostRecent().args[0];
});
it("displays the timer's name", function () {
var element = simpleIndicator.element;
var text = $('.indicator-text', element).text().trim();
expect(text).toEqual('Following timer ' + testObject.name);
});
it("displays the timer's name when it changes", function () {
var secondTimer = {
identifier: {
namespace: 'namespace',
key: 'key2'
},
name: "Some other timer"
};
var element = simpleIndicator.element;
timerService.setTimer(secondTimer);
var text = $('.indicator-text', element).text().trim();
expect(text).toEqual('Following timer ' + secondTimer.name);
});
});
});
});

View File

@@ -161,6 +161,22 @@ define([
evaluate: function (datum, property) {
return limitEvaluator.evaluate(datum, property && property.key);
}
};
};
LegacyTelemetryProvider.prototype.getLimits = function (domainObject) {
const oldObject = this.instantiate(
utils.toOldFormat(domainObject),
utils.makeKeyString(domainObject.identifier)
);
const limitEvaluator = oldObject.getCapability("limit");
return {
limits: function () {
return limitEvaluator.limits();
}
};
};

View File

@@ -215,12 +215,12 @@ define([
* @memberof {module:openmct.CompositionCollection#}
* @name load
*/
CompositionCollection.prototype.load = function () {
CompositionCollection.prototype.load = function (abortSignal) {
this.cleanUpMutables();
return this.provider.load(this.domainObject)
.then(function (children) {
return Promise.all(children.map((c) => this.publicAPI.objects.get(c)));
return Promise.all(children.map((c) => this.publicAPI.objects.get(c, abortSignal)));
}.bind(this))
.then(function (childObjects) {
childObjects.forEach(c => this.add(c, true));

View File

@@ -504,6 +504,26 @@ define([
return this.getLimitEvaluator(domainObject);
};
/**
* Get a limits for this domain object.
* Limits help you display limits and alarms of
* telemetry for display purposes without having to interact directly
* with the Limit API.
*
* This method is optional.
* If a provider does not implement this method, it is presumed
* that no limits are defined for this domain object's telemetry.
*
* @param {module:openmct.DomainObject} domainObject the domain
* object for which to get limits
* @returns {module:openmct.TelemetryAPI~LimitEvaluator}
* @method limits
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
TelemetryAPI.prototype.limitDefinition = function (domainObject) {
return this.getLimits(domainObject);
};
/**
* Get a limit evaluator for this domain object.
* Limit Evaluators help you evaluate limit and alarm status of individual
@@ -531,5 +551,42 @@ define([
return provider.getLimitEvaluator(domainObject);
};
/**
* Get a limit definitions for this domain object.
* Limit Definitions help you indicate limits and alarms of
* telemetry for display purposes without having to interact directly
* with the Limit API.
*
* This method is optional.
* If a provider does not implement this method, it is presumed
* that no limits are defined for this domain object's telemetry.
*
* @param {module:openmct.DomainObject} domainObject the domain
* object for which to display limits
* @returns {module:openmct.TelemetryAPI~LimitEvaluator}
* @method limits returns a limits object of
* type {
* level1: {
* low: { key1: value1, key2: value2 },
* high: { key1: value1, key2: value2 }
* },
* level2: {
* low: { key1: value1, key2: value2 },
* high: { key1: value1, key2: value2 }
* }
* }
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
TelemetryAPI.prototype.getLimits = function (domainObject) {
const provider = this.findLimitEvaluator(domainObject);
if (!provider || !provider.getLimits) {
return {
limits: function () {}
};
}
return provider.getLimits(domainObject);
};
return TelemetryAPI;
});

View File

@@ -43,15 +43,15 @@ export default function LADTableSetViewProvider(openmct) {
components: {
LadTableSet: LadTableSet
},
provide: {
openmct,
objectPath
},
data() {
return {
domainObject
};
},
provide: {
openmct,
objectPath
},
template: '<lad-table-set :domain-object="domainObject"></lad-table-set>'
});
},

View File

@@ -43,6 +43,7 @@ import {TRIGGER_CONJUNCTION, TRIGGER_LABEL} from "./utils/constants";
* }
*/
export default class Condition extends EventEmitter {
/**
* Manages criteria and emits the result of - true or false - based on criteria evaluated.
* @constructor

View File

@@ -19,6 +19,10 @@
margin: 0 $interiorMargin $interiorMargin 0;
}
}
body.mobile & {
flex: 1 0 auto;
}
}
/******************************* GRID ITEMS */

View File

@@ -70,7 +70,7 @@ describe("the plugin", () => {
setTimeout(() => {
expect(window.location.href).toContain('context.html#/browse/?tc.mode=fixed&tc.startBound=0&tc.endBound=1&tc.timeSystem=utc');
done();
}, 2500);
}, 1500);
});
});
});

View File

@@ -32,7 +32,7 @@
:camera-pan="cameraPan"
/>
<CompassRose
v-if="true"
v-if="hasCameraFieldOfView"
:heading="heading"
:sized-image-width="sizedImageDimensions.width"
:sun-heading="sunHeading"

View File

@@ -28,6 +28,7 @@
:series="config.series.models"
:highlights="highlights"
:legend="config.legend"
@legendHoverChanged="legendHoverChanged"
/>
<div class="plot-wrapper-axis-and-display-area flex-elem grows">
<y-axis v-if="config.series.models.length > 0"
@@ -67,6 +68,7 @@
>
<mct-chart :rectangles="rectangles"
:highlights="highlights"
:show-limit-line-labels="showLimitLineLabels"
@plotReinitializeCanvas="initCanvas"
/>
</div>
@@ -159,6 +161,7 @@ import MctTicks from "./MctTicks.vue";
import MctChart from "./chart/MctChart.vue";
import XAxis from "./axis/XAxis.vue";
import YAxis from "./axis/YAxis.vue";
import _ from "lodash";
export default {
components: {
@@ -212,7 +215,8 @@ export default {
pending: 0,
isRealTime: this.openmct.time.clock() !== undefined,
loaded: false,
isTimeOutOfSync: false
isTimeOutOfSync: false,
showLimitLineLabels: undefined
};
},
computed: {
@@ -496,6 +500,10 @@ export default {
},
initialize() {
_.debounce(this.handleWindowResize, 400);
this.plotContainerResizeObserver = new ResizeObserver(this.handleWindowResize);
this.plotContainerResizeObserver.observe(this.$parent.$refs.plotWrapper);
// Setup canvas etc.
this.xScale = new LinearScale(this.config.xAxis.get('displayRange'));
this.yScale = new LinearScale(this.config.yAxis.get('displayRange'));
@@ -999,12 +1007,23 @@ export default {
this.removeStatusListener();
}
this.plotContainerResizeObserver.disconnect();
this.openmct.time.off('clock', this.updateRealTime);
this.openmct.time.off('bounds', this.updateDisplayBounds);
this.openmct.objectViews.off('clearData', this.clearData);
},
updateStatus(status) {
this.$emit('statusUpdated', status);
},
handleWindowResize() {
if (this.offsetWidth !== this.$parent.$refs.plotWrapper.offsetWidth) {
this.offsetWidth = this.$parent.$refs.plotWrapper.offsetWidth;
this.config.series.models.forEach(this.loadSeriesData, this);
}
},
legendHoverChanged(data) {
this.showLimitLineLabels = data;
}
}
};

View File

@@ -0,0 +1,46 @@
<template>
<div class="plot-series-limit-label"
:style="styleObj"
:class="limit.cssClass"
>
<span class="plot-series-limit-value">{{ limit.value }}</span>
<span class="plot-series-color-swatch"
:style="{ 'background-color': limit.color }"
></span>
<span class="plot-series-name">{{ limit.name }}</span>
</div>
</template>
<script>
export default {
props: {
limit: {
type: Object,
required: true,
default() {
return {};
}
},
point: {
type: Object,
required: true,
default() {
return {};
}
}
},
computed: {
styleObj() {
const top = `${this.point.top - 10}px`;
const left = `${this.point.left + 5}px`;
return {
'position': 'absolute',
'top': top,
'left': left,
'color': '#fff'
};
}
}
};
</script>

View File

@@ -0,0 +1,44 @@
<template>
<hr :style="styleObj"
:class="cssWithoutUprLwr"
>
</template>
<script>
export default {
props: {
point: {
type: Object,
required: true,
default() {
return {};
}
},
cssClass: {
type: String,
default() {
return '';
}
}
},
computed: {
styleObj() {
const top = `${this.point.top}px`;
const left = `${this.point.left}px`;
return {
'position': 'absolute',
'width': '100%',
'top': top,
'left': left
};
},
cssWithoutUprLwr() {
let cssClass = this.cssClass.replace(/is-limit--upr/gi, 'is-limit--line');
cssClass = cssClass.replace(/is-limit--lwr/gi, 'is-limit--line');
return cssClass;
}
}
};
</script>

View File

@@ -0,0 +1,105 @@
/*****************************************************************************
* 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 eventHelpers from '../lib/eventHelpers';
export default class MCTChartAlarmLineSet {
constructor(series, chart, offset, bounds) {
this.series = series;
this.chart = chart;
this.offset = offset;
this.bounds = bounds;
this.limits = [];
eventHelpers.extend(this);
this.listenTo(series, 'limitBounds', this.updateBounds, this);
this.listenTo(series, 'change:xKey', this.getLimitPoints, this);
if (series.limits) {
this.getLimitPoints(series);
}
}
updateBounds(bounds) {
this.bounds = bounds;
this.getLimitPoints(this.series);
}
color() {
return this.series.get('color');
}
name() {
return this.series.get('name');
}
makePoint(point, series) {
if (!this.offset.xVal) {
this.chart.setOffset(point, undefined, series);
}
return {
x: this.offset.xVal(point, series),
y: this.offset.yVal(point, series)
};
}
getLimitPoints(series) {
this.limits = [];
let xKey = series.get('xKey');
Object.keys(series.limits).forEach((key) => {
const limitForLevel = series.limits[key];
if (limitForLevel.high) {
const point = this.makePoint(Object.assign({ [xKey]: this.bounds.start }, limitForLevel.high), series);
this.limits.push({
seriesKey: series.keyString,
value: series.getYVal(limitForLevel.high),
color: this.color().asHexString(),
name: this.name(),
point,
cssClass: limitForLevel.high.cssClass
});
}
if (limitForLevel.low) {
const point = this.makePoint(Object.assign({ [xKey]: this.bounds.start }, limitForLevel.low), series);
this.limits.push({
seriesKey: series.keyString,
value: series.getYVal(limitForLevel.low),
color: this.color().asHexString(),
name: this.name(),
point,
cssClass: limitForLevel.low.cssClass
});
}
}, this);
}
reset() {
this.limits = [];
}
destroy() {
this.stopListening();
}
}

View File

@@ -23,6 +23,9 @@
<div class="gl-plot-chart-area">
<span v-html="canvasTemplate"></span>
<span v-html="canvasTemplate"></span>
<div ref="limitArea"
class="js-limit-area"
></div>
</div>
</template>
@@ -34,8 +37,12 @@ import MCTChartLineLinear from './MCTChartLineLinear';
import MCTChartLineStepAfter from './MCTChartLineStepAfter';
import MCTChartPointSet from './MCTChartPointSet';
import MCTChartAlarmPointSet from './MCTChartAlarmPointSet';
import MCTChartAlarmLineSet from "./MCTChartAlarmLineSet";
import configStore from "../configuration/configStore";
import PlotConfigurationModel from "../configuration/PlotConfigurationModel";
import LimitLine from "./LimitLine.vue";
import LimitLabel from "./LimitLabel.vue";
import Vue from 'vue';
const MARKER_SIZE = 6.0;
const HIGHLIGHT_SIZE = MARKER_SIZE * 2.0;
@@ -54,6 +61,12 @@ export default {
default() {
return [];
}
},
showLimitLineLabels: {
type: Object,
default() {
return {};
}
}
},
data() {
@@ -67,18 +80,22 @@ export default {
},
rectangles() {
this.scheduleDraw();
},
showLimitLineLabels() {
this.drawLimitLines();
}
},
mounted() {
eventHelpers.extend(this);
this.config = this.getConfig();
this.isDestroyed = false;
this.lines = [];
this.limitLines = [];
this.pointSets = [];
this.alarmSets = [];
this.offset = {};
this.seriesElements = new WeakMap();
this.seriesLimits = new WeakMap();
let canvasEls = this.$parent.$refs.chartContainer.querySelectorAll("canvas");
const mainCanvas = canvasEls[1];
@@ -90,8 +107,8 @@ export default {
this.listenTo(this.config.series, 'add', this.onSeriesAdd, this);
this.listenTo(this.config.series, 'remove', this.onSeriesRemove, this);
this.listenTo(this.config.yAxis, 'change:key', this.clearOffset, this);
this.listenTo(this.config.yAxis, 'change', this.scheduleDraw);
this.listenTo(this.config.xAxis, 'change', this.scheduleDraw);
this.listenTo(this.config.yAxis, 'change', this.updateLimitsAndDraw);
this.listenTo(this.config.xAxis, 'change', this.updateLimitsAndDraw);
this.config.series.forEach(this.onSeriesAdd, this);
},
beforeDestroy() {
@@ -116,15 +133,18 @@ export default {
this.changeInterpolate(mode, o, series);
this.changeMarkers(mode, o, series);
this.changeAlarmMarkers(mode, o, series);
this.changeLimitLines(mode, o, series);
},
onSeriesAdd(series) {
this.listenTo(series, 'change:xKey', this.reDraw, this);
this.listenTo(series, 'change:interpolate', this.changeInterpolate, this);
this.listenTo(series, 'change:markers', this.changeMarkers, this);
this.listenTo(series, 'change:alarmMarkers', this.changeAlarmMarkers, this);
this.listenTo(series, 'change:limitLines', this.changeLimitLines, this);
this.listenTo(series, 'change', this.scheduleDraw);
this.listenTo(series, 'add', this.scheduleDraw);
this.makeChartElement(series);
this.makeLimitLines(series);
},
changeInterpolate(mode, o, series) {
if (mode === o) {
@@ -178,6 +198,14 @@ export default {
this.pointSets.push(pointSet);
}
},
changeLimitLines(mode, o, series) {
if (mode === o) {
return;
}
this.makeLimitLines(series);
this.updateLimitsAndDraw();
},
onSeriesRemove(series) {
this.stopListening(series);
this.removeChartElement(series);
@@ -187,6 +215,7 @@ export default {
this.isDestroyed = true;
this.stopListening();
this.lines.forEach(line => line.destroy());
this.limitLines.forEach(line => line.destroy());
DrawLoader.releaseDrawAPI(this.drawAPI);
},
clearOffset() {
@@ -199,6 +228,9 @@ export default {
this.lines.forEach(function (line) {
line.reset();
});
this.limitLines.forEach(function (line) {
line.reset();
});
this.pointSets.forEach(function (pointSet) {
pointSet.reset();
});
@@ -269,6 +301,8 @@ export default {
}
this.seriesElements.delete(series);
this.clearLimitLines(series);
},
lineForSeries(series) {
if (series.get('interpolate') === 'linear') {
@@ -287,6 +321,14 @@ export default {
);
}
},
limitLineForSeries(series) {
return new MCTChartAlarmLineSet(
series,
this,
this.offset,
this.openmct.time.bounds()
);
},
pointSetForSeries(series) {
if (series.get('markers')) {
return new MCTChartPointSet(
@@ -308,7 +350,8 @@ export default {
makeChartElement(series) {
const elements = {
lines: [],
pointSets: []
pointSets: [],
limitLines: []
};
const line = this.lineForSeries(series);
@@ -330,6 +373,37 @@ export default {
this.seriesElements.set(series, elements);
},
makeLimitLines(series) {
this.clearLimitLines(series);
if (!series.get('limitLines')) {
return;
}
const limitElements = {
limitLines: []
};
const limitLine = this.limitLineForSeries(series);
if (limitLine) {
limitElements.limitLines.push(limitLine);
this.limitLines.push(limitLine);
}
this.seriesLimits.set(series, limitElements);
},
clearLimitLines(series) {
const seriesLimits = this.seriesLimits.get(series);
if (seriesLimits) {
seriesLimits.limitLines.forEach(function (line) {
this.limitLines.splice(this.limitLines.indexOf(line), 1);
line.destroy();
}, this);
this.seriesLimits.delete(series);
}
},
canDraw() {
if (!this.offset.x || !this.offset.y) {
return false;
@@ -337,6 +411,10 @@ export default {
return true;
},
updateLimitsAndDraw() {
this.drawLimitLines();
this.scheduleDraw();
},
scheduleDraw() {
if (!this.drawScheduled) {
requestAnimationFrame(this.draw);
@@ -385,6 +463,68 @@ export default {
this.pointSets.forEach(this.drawPoints, this);
this.alarmSets.forEach(this.drawAlarmPoints, this);
},
drawLimitLines() {
if (this.canDraw()) {
this.updateViewport();
if (!this.drawAPI.origin) {
return;
}
Array.from(this.$refs.limitArea.children).forEach((el) => el.remove());
this.limitLines.forEach((limitLine) => {
let limitContainerEl = this.$refs.limitArea;
limitLine.limits.forEach((limit) => {
const showLabels = this.showLabels(limit.seriesKey);
if (showLabels) {
let limitLabelEl = this.getLimitLabel(limit);
limitContainerEl.appendChild(limitLabelEl);
}
let limitEl = this.getLimitElement(limit);
limitContainerEl.appendChild(limitEl);
}, this);
});
}
},
showLabels(seriesKey) {
return this.showLimitLineLabels.seriesKey
&& (this.showLimitLineLabels.seriesKey === seriesKey);
},
getLimitElement(limit) {
let point = {
left: 0,
top: this.drawAPI.y(limit.point.y)
};
let LimitLineClass = Vue.extend(LimitLine);
const component = new LimitLineClass({
propsData: {
point,
cssClass: limit.cssClass
}
});
component.$mount();
return component.$el;
},
getLimitLabel(limit) {
let point = {
left: 0,
top: this.drawAPI.y(limit.point.y)
};
let LimitLabelClass = Vue.extend(LimitLabel);
const component = new LimitLabelClass({
propsData: {
limit,
point
}
});
component.$mount();
return component.$el;
},
drawAlarmPoints(alarmSet) {
this.drawAPI.drawLimitPoints(
alarmSet.points,
@@ -401,11 +541,12 @@ export default {
chartElement.series.get('markerShape')
);
},
drawLine(chartElement) {
drawLine(chartElement, disconnected) {
this.drawAPI.drawLine(
chartElement.getBuffer(),
chartElement.color().asRGBAArray(),
chartElement.count
chartElement.count,
disconnected
);
},
drawHighlights() {

View File

@@ -97,7 +97,8 @@ export default class PlotSeries extends Model {
markers: true,
markerShape: 'point',
markerSize: 2.0,
alarmMarkers: true
alarmMarkers: true,
limitLines: false
};
}
@@ -115,9 +116,16 @@ export default class PlotSeries extends Model {
this.domainObject = options.domainObject;
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(options.domainObject);
this.limitDefinition = this.openmct.telemetry.limitDefinition(options.domainObject);
this.limits = this.limitDefinition.limits();
this.openmct.time.on('bounds', this.updateLimits);
this.on('destroy', this.onDestroy, this);
}
updateLimits(bounds) {
this.emit('limitBounds', bounds);
}
locateOldObject(oldStyleParent) {
return oldStyleParent.useCapability('composition')
.then(function (children) {

View File

@@ -60,6 +60,14 @@
{{ alarmMarkers ? "Enabled" : "Disabled" }}
</div>
</li>
<li class="grid-row">
<div class="grid-cell label"
title="Display lines visually denoting alarm limits."
>Limit lines</div>
<div class="grid-cell value">
{{ limitLines ? "Enabled" : "Disabled" }}
</div>
</li>
<li class="grid-row">
<div class="grid-cell label"
title="The plot line and marker color for this series."
@@ -135,6 +143,9 @@ export default {
alarmMarkers() {
return this.series.get('alarmMarkers');
},
limitLines() {
return this.series.get('limitLines');
},
seriesHexColor() {
return this.series.get('color').asHexString();
}

View File

@@ -91,6 +91,17 @@
>
</div>
</li>
<li class="grid-row">
<div class="grid-cell label"
title="Display limit lines"
>Limit lines</div>
<div class="grid-cell value">
<input v-model="limitLines"
type="checkbox"
@change="updateForm('limitLines')"
>
</div>
</li>
<li v-show="markers || alarmMarkers"
class="grid-row"
>
@@ -168,6 +179,7 @@ export default {
markers: this.series.get('markers'),
markerShape: this.series.get('markerShape'),
alarmMarkers: this.series.get('alarmMarkers'),
limitLines: this.series.get('limitLines'),
markerSize: this.series.get('markerSize'),
validation: {},
swatchActive: false
@@ -240,6 +252,11 @@ export default {
modelProp: 'alarmMarkers',
coerce: Boolean,
objectPath: this.dynamicPathForKey('alarmMarkers')
},
{
modelProp: 'limitLines',
coerce: Boolean,
objectPath: this.dynamicPathForKey('limitLines')
}
];

View File

@@ -48,7 +48,7 @@
:highlights="highlights"
:value-to-show-when-collapsed="legend.get('valueToShowWhenCollapsed')"
:series-object="seriesObject"
:closest="seriesObject.closest"
@legendHoverChanged="legendHoverChanged"
/>
</div>
<!-- EXPANDED PLOT LEGEND -->
@@ -89,6 +89,7 @@
:series-object="seriesObject"
:highlights="highlights"
:legend="legend"
@legendHoverChanged="legendHoverChanged"
/>
</tbody>
</table>
@@ -133,19 +134,36 @@ export default {
},
data() {
return {
isLegendHidden: this.legend.get('hideLegendWhenSmall') !== true,
isLegendExpanded: this.legend.get('expanded') === true,
showTimestampWhenExpanded: this.legend.get('showTimestampWhenExpanded') === true,
showValueWhenExpanded: this.legend.get('showValueWhenExpanded') === true,
showUnitsWhenExpanded: this.legend.get('showUnitsWhenExpanded') === true,
showMinimumWhenExpanded: this.legend.get('showMinimumWhenExpanded') === true,
showMaximumWhenExpanded: this.legend.get('showMaximumWhenExpanded') === true
isLegendExpanded: this.legend.get('expanded') === true
};
},
computed: {
showUnitsWhenExpanded() {
return this.legend.get('showUnitsWhenExpanded') === true;
},
showMinimumWhenExpanded() {
return this.legend.get('showMinimumWhenExpanded') === true;
},
showMaximumWhenExpanded() {
return this.legend.get('showMaximumWhenExpanded') === true;
},
showValueWhenExpanded() {
return this.legend.get('showValueWhenExpanded') === true;
},
showTimestampWhenExpanded() {
return this.legend.get('showTimestampWhenExpanded') === true;
},
isLegendHidden() {
return this.legend.get('hideLegendWhenSmall') === true;
}
},
methods: {
expandLegend() {
this.isLegendExpanded = !this.isLegendExpanded;
this.legend.set('expanded', this.isLegendExpanded);
},
legendHoverChanged(data) {
this.$emit('legendHoverChanged', data);
}
}
};

View File

@@ -24,6 +24,8 @@
:class="{
'is-status--missing': isMissing
}"
@mouseover="toggleHover(true)"
@mouseleave="toggleHover(false)"
>
<div class="plot-series-swatch-and-name">
<span class="plot-series-color-swatch"
@@ -121,6 +123,12 @@ export default {
} else {
this.formattedYValueFromStats = '';
}
},
toggleHover(hover) {
this.hover = hover;
this.$emit('legendHoverChanged', {
seriesKey: this.hover ? this.seriesObject.keyString : ''
});
}
}
};

View File

@@ -25,6 +25,8 @@
:class="{
'is-status--missing': isMissing
}"
@mouseover="toggleHover(true)"
@mouseleave="toggleHover(false)"
>
<td class="plot-series-swatch-and-name">
<span class="plot-series-color-swatch"
@@ -94,11 +96,6 @@ export default {
},
data() {
return {
showTimestampWhenExpanded: this.legend.get('showTimestampWhenExpanded'),
showValueWhenExpanded: this.legend.get('showValueWhenExpanded'),
showUnitsWhenExpanded: this.legend.get('showUnitsWhenExpanded'),
showMinimumWhenExpanded: this.legend.get('showMinimumWhenExpanded'),
showMaximumWhenExpanded: this.legend.get('showMaximumWhenExpanded'),
isMissing: false,
colorAsHexString: '',
name: '',
@@ -110,6 +107,23 @@ export default {
mctLimitStateClass: ''
};
},
computed: {
showUnitsWhenExpanded() {
return this.legend.get('showUnitsWhenExpanded') === true;
},
showMinimumWhenExpanded() {
return this.legend.get('showMinimumWhenExpanded') === true;
},
showMaximumWhenExpanded() {
return this.legend.get('showMaximumWhenExpanded') === true;
},
showValueWhenExpanded() {
return this.legend.get('showValueWhenExpanded') === true;
},
showTimestampWhenExpanded() {
return this.legend.get('showTimestampWhenExpanded') === true;
}
},
watch: {
highlights(newHighlights) {
const highlightedObject = newHighlights.find(highlight => highlight.series.keyString === this.seriesObject.keyString);
@@ -148,6 +162,12 @@ export default {
this.formattedMinY = '';
this.formattedMaxY = '';
}
},
toggleHover(hover) {
this.hover = hover;
this.$emit('legendHoverChanged', {
seriesKey: this.hover ? this.seriesObject.keyString : ''
});
}
}
};

View File

@@ -36,6 +36,7 @@ describe("the plugin", function () {
let telemetryPromise;
let cleanupFirst;
let mockObjectPath;
let telemetrylimitProvider;
beforeEach((done) => {
mockObjectPath = [
@@ -88,6 +89,45 @@ describe("the plugin", function () {
return telemetryPromise;
});
telemetrylimitProvider = jasmine.createSpyObj('telemetrylimitProvider', [
'supportsLimits',
'getLimits',
'getLimitEvaluator'
]);
telemetrylimitProvider.supportsLimits.and.returnValue(true);
telemetrylimitProvider.getLimits.and.returnValue({
limits: function () {
return {
WARNING: {
low: {
cssClass: "is-limit--lwr is-limit--yellow",
'some-key': -0.5
},
high: {
cssClass: "is-limit--upr is-limit--yellow",
'some-key': 0.5
}
},
DISTRESS: {
low: {
cssClass: "is-limit--lwr is-limit--red",
'some-key': -0.9
},
high: {
cssClass: "is-limit--upr is-limit--red",
'some-key': 0.9
}
}
};
}
});
telemetrylimitProvider.getLimitEvaluator.and.returnValue({
evaluate: function () {
return {};
}
});
openmct.telemetry.addProvider(telemetrylimitProvider);
openmct.install(new PlotVuePlugin());
element = document.createElement("div");
@@ -99,6 +139,11 @@ describe("the plugin", function () {
element.appendChild(child);
document.body.appendChild(element);
spyOn(window, 'ResizeObserver').and.returnValue({
observe() {},
disconnect() {}
});
openmct.time.timeSystem("utc", {
start: 0,
end: 4
@@ -652,6 +697,25 @@ describe("the plugin", function () {
done();
});
});
describe('limits', () => {
it('lines are not displayed by default', () => {
let limitEl = element.querySelectorAll(".js-limit-area hr");
expect(limitEl.length).toBe(0);
});
it('lines are displayed when configuration is set to true', (done) => {
config.series.models[0].set('limitLines', true);
Vue.nextTick(() => {
let limitEl = element.querySelectorAll(".js-limit-area hr");
expect(limitEl.length).toBe(4);
done();
});
});
});
});
describe('the inspector view', () => {
@@ -798,7 +862,7 @@ describe("the plugin", function () {
expandControl.dispatchEvent(clickEvent);
const plotOptionsProperties = browseOptionsEl.querySelectorAll('.js-plot-options-browse-properties .grid-row');
expect(plotOptionsProperties.length).toEqual(5);
expect(plotOptionsProperties.length).toEqual(6);
});
});
@@ -840,7 +904,7 @@ describe("the plugin", function () {
expandControl.dispatchEvent(clickEvent);
const plotOptionsProperties = editOptionsEl.querySelectorAll(".js-plot-options-edit-properties .grid-row");
expect(plotOptionsProperties.length).toEqual(6);
expect(plotOptionsProperties.length).toEqual(7);
});
it('shows yKeyOptions', () => {

View File

@@ -83,9 +83,9 @@
@update="timePopUpdate"
/>
<button
@click="showTimePopupStart"
class="c-button c-conductor__delta-button"
ref="startOffset"
class="c-button c-conductor__delta-button"
@click="showTimePopupStart"
>
{{ offsets.start }}
</button>
@@ -135,7 +135,7 @@
class="c-button c-conductor__delta-button"
@click="showTimePopupEnd"
>
{{offsets.end}}
{{ offsets.end }}
</button>
</div>

View File

@@ -362,7 +362,7 @@ $legendTableHeadBg: $colorTabHeaderBg;
// Tree
$colorTreeBg: transparent;
$colorItemTreeHoverBg: rgba(#fff, 0.03);
$colorItemTreeHoverBg: rgba(#fff, 0.1);
$colorItemTreeHoverFg: #fff;
$colorItemTreeIcon: $colorKey; // Used
$colorItemTreeIconHover: $colorItemTreeIcon; // Used

View File

@@ -212,6 +212,7 @@ $glyph-icon-3-dots: '\ea37';
$glyph-icon-grid-on: '\ea38';
$glyph-icon-grid-off: '\ea39';
$glyph-icon-camera: '\ea3a';
$glyph-icon-folders-collapse: '\ea3b';
$glyph-icon-activity: '\eb00';
$glyph-icon-activity-mode: '\eb01';
$glyph-icon-autoflow-tabular: '\eb02';

View File

@@ -144,6 +144,7 @@
.icon-grid-on { @include glyphBefore($glyph-icon-grid-on); }
.icon-grid-off { @include glyphBefore($glyph-icon-grid-off); }
.icon-camera { @include glyphBefore($glyph-icon-camera); }
.icon-folders-collapse { @include glyphBefore($glyph-icon-folders-collapse); }
.icon-activity { @include glyphBefore($glyph-icon-activity); }
.icon-activity-mode { @include glyphBefore($glyph-icon-activity-mode); }
.icon-autoflow-tabular { @include glyphBefore($glyph-icon-autoflow-tabular); }

View File

@@ -531,7 +531,7 @@ mct-plot {
}
/***************** GENERAL STYLES, ALL STATES */
.plot-legend-item {
.plot-legend-item, .plot-series-limit-label {
// General styles for legend items, both expanded and collapsed legend states
> * + * {
margin-left: $interiorMarginSm;

View File

@@ -70,6 +70,10 @@
&.is-limit--lwr:before { content: $glyph-icon-arrow-down !important; }
}
@mixin andLine {
&.is-limit--line:before { content: '' !important; }
}
@mixin uIndicator($bg, $fg, $glyph) {
background: $bg;
color: $fg;
@@ -100,12 +104,14 @@
@include statusStyle($colorLimitYellowBg, $colorLimitYellowFg, true);
@include statusIcon($colorLimitYellowIc, $glyph-icon-alert-rect);
@include andUprLwr();
@include andLine();
}
&.is-limit--red {
@include statusStyle($colorLimitRedBg, $colorLimitRedFg, true);
@include statusIcon($colorLimitRedIc, $glyph-icon-alert-triangle);
@include andUprLwr();
@include andLine();
}
}

View File

@@ -2,7 +2,7 @@
"metadata": {
"name": "Open MCT Symbols 16px",
"lastOpened": 0,
"created": 1602779919972
"created": 1621648023886
},
"iconSets": [
{
@@ -847,13 +847,21 @@
"code": 59962,
"tempChar": ""
},
{
"order": 196,
"id": 168,
"name": "icon-folders-collapse",
"prevSize": 24,
"code": 59963,
"tempChar": ""
},
{
"order": 144,
"id": 97,
"name": "icon-activity",
"prevSize": 24,
"code": 60160,
"tempChar": ""
"tempChar": ""
},
{
"order": 104,
@@ -861,7 +869,7 @@
"name": "icon-activity-mode",
"prevSize": 24,
"code": 60161,
"tempChar": ""
"tempChar": ""
},
{
"order": 137,
@@ -869,7 +877,7 @@
"name": "icon-autoflow-tabular",
"prevSize": 24,
"code": 60162,
"tempChar": ""
"tempChar": ""
},
{
"order": 115,
@@ -877,7 +885,7 @@
"name": "icon-clock",
"prevSize": 24,
"code": 60163,
"tempChar": ""
"tempChar": ""
},
{
"order": 2,
@@ -885,7 +893,7 @@
"name": "icon-database",
"prevSize": 24,
"code": 60164,
"tempChar": ""
"tempChar": ""
},
{
"order": 3,
@@ -893,7 +901,7 @@
"name": "icon-database-query",
"prevSize": 24,
"code": 60165,
"tempChar": ""
"tempChar": ""
},
{
"order": 67,
@@ -901,7 +909,7 @@
"name": "icon-dataset",
"prevSize": 24,
"code": 60166,
"tempChar": ""
"tempChar": ""
},
{
"order": 59,
@@ -909,7 +917,7 @@
"name": "icon-datatable",
"prevSize": 24,
"code": 60167,
"tempChar": ""
"tempChar": ""
},
{
"order": 136,
@@ -917,7 +925,7 @@
"name": "icon-dictionary",
"prevSize": 24,
"code": 60168,
"tempChar": ""
"tempChar": ""
},
{
"order": 51,
@@ -925,7 +933,7 @@
"name": "icon-folder",
"prevSize": 24,
"code": 60169,
"tempChar": ""
"tempChar": ""
},
{
"order": 147,
@@ -933,7 +941,7 @@
"name": "icon-image",
"prevSize": 24,
"code": 60170,
"tempChar": ""
"tempChar": ""
},
{
"order": 4,
@@ -941,7 +949,7 @@
"name": "icon-layout",
"prevSize": 24,
"code": 60171,
"tempChar": ""
"tempChar": ""
},
{
"order": 24,
@@ -949,7 +957,7 @@
"name": "icon-object",
"prevSize": 24,
"code": 60172,
"tempChar": ""
"tempChar": ""
},
{
"order": 52,
@@ -957,7 +965,7 @@
"name": "icon-object-unknown",
"prevSize": 24,
"code": 60173,
"tempChar": ""
"tempChar": ""
},
{
"order": 105,
@@ -965,7 +973,7 @@
"name": "icon-packet",
"prevSize": 24,
"code": 60174,
"tempChar": ""
"tempChar": ""
},
{
"order": 126,
@@ -973,7 +981,7 @@
"name": "icon-page",
"prevSize": 24,
"code": 60175,
"tempChar": ""
"tempChar": ""
},
{
"order": 130,
@@ -981,7 +989,7 @@
"name": "icon-plot-overlay",
"prevSize": 24,
"code": 60176,
"tempChar": ""
"tempChar": ""
},
{
"order": 80,
@@ -989,7 +997,7 @@
"name": "icon-plot-stacked",
"prevSize": 24,
"code": 60177,
"tempChar": ""
"tempChar": ""
},
{
"order": 134,
@@ -997,7 +1005,7 @@
"name": "icon-session",
"prevSize": 24,
"code": 60178,
"tempChar": ""
"tempChar": ""
},
{
"order": 109,
@@ -1005,7 +1013,7 @@
"name": "icon-tabular",
"prevSize": 24,
"code": 60179,
"tempChar": ""
"tempChar": ""
},
{
"order": 107,
@@ -1013,7 +1021,7 @@
"name": "icon-tabular-lad",
"prevSize": 24,
"code": 60180,
"tempChar": ""
"tempChar": ""
},
{
"order": 106,
@@ -1021,7 +1029,7 @@
"name": "icon-tabular-lad-set",
"prevSize": 24,
"code": 60181,
"tempChar": ""
"tempChar": ""
},
{
"order": 70,
@@ -1029,7 +1037,7 @@
"name": "icon-tabular-realtime",
"prevSize": 24,
"code": 60182,
"tempChar": ""
"tempChar": ""
},
{
"order": 60,
@@ -1037,7 +1045,7 @@
"name": "icon-tabular-scrolling",
"prevSize": 24,
"code": 60183,
"tempChar": ""
"tempChar": ""
},
{
"order": 131,
@@ -1045,7 +1053,7 @@
"name": "icon-telemetry",
"prevSize": 24,
"code": 60184,
"tempChar": ""
"tempChar": ""
},
{
"order": 108,
@@ -1053,7 +1061,7 @@
"name": "icon-timeline",
"prevSize": 24,
"code": 60185,
"tempChar": ""
"tempChar": ""
},
{
"order": 81,
@@ -1061,7 +1069,7 @@
"name": "icon-timer",
"prevSize": 24,
"code": 60186,
"tempChar": ""
"tempChar": ""
},
{
"order": 69,
@@ -1069,7 +1077,7 @@
"name": "icon-topic",
"prevSize": 24,
"code": 60187,
"tempChar": ""
"tempChar": ""
},
{
"order": 79,
@@ -1077,7 +1085,7 @@
"name": "icon-box-with-dashed-lines-v2",
"prevSize": 24,
"code": 60188,
"tempChar": ""
"tempChar": ""
},
{
"order": 90,
@@ -1085,7 +1093,7 @@
"name": "icon-summary-widget",
"prevSize": 24,
"code": 60189,
"tempChar": ""
"tempChar": ""
},
{
"order": 92,
@@ -1093,7 +1101,7 @@
"name": "icon-notebook",
"prevSize": 24,
"code": 60190,
"tempChar": ""
"tempChar": ""
},
{
"order": 168,
@@ -1101,7 +1109,7 @@
"name": "icon-tabs-view",
"prevSize": 24,
"code": 60191,
"tempChar": ""
"tempChar": ""
},
{
"order": 117,
@@ -1109,7 +1117,7 @@
"name": "icon-flexible-layout",
"prevSize": 24,
"code": 60192,
"tempChar": ""
"tempChar": ""
},
{
"order": 166,
@@ -1117,7 +1125,7 @@
"name": "icon-generator-sine",
"prevSize": 24,
"code": 60193,
"tempChar": ""
"tempChar": ""
},
{
"order": 167,
@@ -1125,7 +1133,7 @@
"name": "icon-generator-event",
"prevSize": 24,
"code": 60194,
"tempChar": ""
"tempChar": ""
},
{
"order": 165,
@@ -1133,7 +1141,7 @@
"name": "icon-gauge-v2",
"prevSize": 24,
"code": 60195,
"tempChar": ""
"tempChar": ""
},
{
"order": 170,
@@ -1141,7 +1149,7 @@
"name": "icon-spectra",
"prevSize": 24,
"code": 60196,
"tempChar": ""
"tempChar": ""
},
{
"order": 171,
@@ -1149,7 +1157,7 @@
"name": "icon-telemetry-spectra",
"prevSize": 24,
"code": 60197,
"tempChar": ""
"tempChar": ""
},
{
"order": 172,
@@ -1157,7 +1165,7 @@
"name": "icon-pushbutton",
"prevSize": 24,
"code": 60198,
"tempChar": ""
"tempChar": ""
},
{
"order": 174,
@@ -1165,7 +1173,7 @@
"name": "icon-conditional",
"prevSize": 24,
"code": 60199,
"tempChar": ""
"tempChar": ""
},
{
"order": 178,
@@ -1173,7 +1181,7 @@
"name": "icon-condition-widget",
"prevSize": 24,
"code": 60200,
"tempChar": ""
"tempChar": ""
},
{
"order": 180,
@@ -1181,7 +1189,7 @@
"name": "icon-alphanumeric",
"prevSize": 24,
"code": 60201,
"tempChar": ""
"tempChar": ""
},
{
"order": 183,
@@ -1189,7 +1197,7 @@
"name": "icon-image-telemetry",
"prevSize": 24,
"code": 60202,
"tempChar": ""
"tempChar": ""
}
],
"id": 0,
@@ -2993,6 +3001,29 @@
]
}
},
{
"id": 168,
"paths": [
"M896 320v448c-0.215 70.606-57.394 127.785-127.979 128l-0.021 0h-576c0.215 70.606 57.394 127.785 127.979 128l0.021 0h576c70.606-0.215 127.785-57.394 128-127.979l0-0.021v-448c-0.215-70.606-57.394-127.785-127.979-128l-0.021-0z",
"M832 704v-448c-0.215-70.606-57.394-127.785-127.979-128l-0.021-0h-192l-101.5-82.74c-24.88-24.9-74.040-45.26-109.24-45.26h-237.26c-35.305 0.102-63.898 28.695-64 63.99l-0 0.010v640c0.215 70.606 57.394 127.785 127.979 128l0.021 0h576c70.606-0.215 127.785-57.394 128-127.979l0-0.021zM128 644v-516l256 260z"
],
"attrs": [
{},
{}
],
"grid": 16,
"tags": [
"icon-folders-collapse"
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"12552552551": [
{},
{}
]
}
},
{
"id": 97,
"paths": [

View File

@@ -112,6 +112,7 @@
<glyph unicode="&#xea38;" glyph-name="icon-grid-on" d="M1024 448v128h-256v256h-128v-256h-256v256h-128v-256h-256v-128h256v-256h-256v-128h256v-256h128v256h256v-256h128v256h256v128h-256v256zM640 192h-256v256h256z" />
<glyph unicode="&#xea39;" glyph-name="icon-grid-off" d="M256 280.6l128 157.6v9.8h8l104 128h-112v256h-128v-256h-256v-128h256v-167.4zM184 192h-184v-128h80l104 128zM768 359.4l-128-157.6v-9.8h-8l-104-128h112v-256h128v256h256v128h-256v167.4zM840 448h184v128h-80l-104-128zM832 832l-832-1024h192l832 1024h-192z" />
<glyph unicode="&#xea3a;" glyph-name="icon-camera" d="M896 576h-128l-128 256h-256l-128-256h-128c-70.601-0.227-127.773-57.399-128-127.978v-512.022c0.227-70.601 57.399-127.773 127.978-128h768.022c70.601 0.227 127.773 57.399 128 127.978v512.022c-0.227 70.601-57.399 127.773-127.978 128h-0.022zM512-32c-141.385 0-256 114.615-256 256s114.615 256 256 256c141.385 0 256-114.615 256-256v0c0-141.385-114.615-256-256-256v0z" />
<glyph unicode="&#xea3b;" glyph-name="icon-folders-collapse" d="M896 512v-448c-0.215-70.606-57.394-127.785-127.979-128h-576.021c0.215-70.606 57.394-127.785 127.979-128h576.021c70.606 0.215 127.785 57.394 128 127.979v448.021c-0.215 70.606-57.394 127.785-127.979 128h-0.021zM832 128v448c-0.215 70.606-57.394 127.785-127.979 128h-192.021l-101.5 82.74c-24.88 24.9-74.040 45.26-109.24 45.26h-237.26c-35.305-0.102-63.898-28.695-64-63.99v-640.010c0.215-70.606 57.394-127.785 127.979-128h576.021c70.606 0.215 127.785 57.394 128 127.979v0.021zM128 188v516l256-260z" />
<glyph unicode="&#xeb00;" glyph-name="icon-activity" d="M576 768h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" />
<glyph unicode="&#xeb01;" glyph-name="icon-activity-mode" d="M512 832c-214.8 0-398.8-132.4-474.8-320h90.8c56.8 0 108-24.8 143-64h241l-192 192h256l320-320-320-320h-256l192 192h-241c-35-39.2-86.2-64-143-64h-90.8c76-187.6 259.8-320 474.8-320 282.8 0 512 229.2 512 512s-229.2 512-512 512z" />
<glyph unicode="&#xeb02;" glyph-name="icon-autoflow-tabular" d="M192 832c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 832h256v-1024h-256v1024zM832 832h-64v-704h256v512c0 105.6-86.4 192-192 192z" />

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -118,10 +118,11 @@ export default {
this.openmct.objectViews.off('clearData', this.clearData);
},
getStyleReceiver() {
let styleReceiver = this.$el.querySelector('.js-style-receiver');
let styleReceiver = this.$el.querySelector('.js-style-receiver')
|| this.$el.querySelector(':first-child');
if (!styleReceiver) {
styleReceiver = this.$el.querySelector(':first-child');
if (styleReceiver === null) {
styleReceiver = undefined;
}
return styleReceiver;
@@ -142,12 +143,13 @@ export default {
this.updateView(true);
},
updateStyle(styleObj) {
if (!styleObj) {
let elemToStyle = this.getStyleReceiver();
if (!styleObj || elemToStyle === undefined) {
return;
}
let keys = Object.keys(styleObj);
let elemToStyle = this.getStyleReceiver();
keys.forEach(key => {
if (elemToStyle) {
@@ -373,11 +375,17 @@ export default {
},
setFontSize(newSize) {
let elemToStyle = this.getStyleReceiver();
elemToStyle.dataset.fontSize = newSize;
if (elemToStyle !== undefined) {
elemToStyle.dataset.fontSize = newSize;
}
},
setFont(newFont) {
let elemToStyle = this.getStyleReceiver();
elemToStyle.dataset.font = newFont;
if (elemToStyle !== undefined) {
elemToStyle.dataset.font = newFont;
}
}
}
};

View File

@@ -54,6 +54,13 @@
label="Browse"
collapsable
>
<button
slot="controls"
class="c-icon-button l-shell__reset-tree-button icon-folders-collapse"
title="Collapse all tree items"
@click="handleTreeReset"
>
</button>
<button
slot="controls"
class="c-icon-button l-shell__sync-tree-button icon-target"
@@ -63,6 +70,7 @@
</button>
<mct-tree
:sync-tree-navigation="triggerSync"
:reset-tree-navigation="triggerReset"
class="l-shell__tree"
/>
</pane>
@@ -148,6 +156,7 @@ export default {
hasToolbar: false,
actionCollection: undefined,
triggerSync: false,
triggerReset: false,
headExpanded
};
},
@@ -228,6 +237,9 @@ export default {
},
handleSyncTreeNavigation() {
this.triggerSync = !this.triggerSync;
},
handleTreeReset() {
this.triggerReset = !this.triggerReset;
}
}
};

View File

@@ -100,8 +100,14 @@
&__pane-tree {
background: linear-gradient(90deg, transparent 70%, rgba(black, 0.2) 99%, rgba(black, 0.3));
[class*="expand-button"],
[class*="sync-tree-button"] {
.l-pane__header {
// Hide all buttons except the collapse button
> :not(.l-pane__collapse-button) {
display: none;
}
}
[class*="expand-button"] {
display: none;
}

View File

@@ -30,7 +30,7 @@
width: 100%;
}
&__scrollable-children {
&__scrollable {
overflow: auto;
}
@@ -56,6 +56,7 @@
@include userSelectNone();
overflow-x: hidden;
overflow-y: auto;
padding-right: $interiorMarginSm;
.icon-arrow-nav-to-parent {
visibility: hidden;
@@ -90,7 +91,7 @@
color: $colorItemTreeIcon;
}
&:hover {
@include hover {
background: $colorItemTreeHoverBg;
filter: $filterHov;
}
@@ -124,14 +125,16 @@
}
&__item {
> * + * {
margin-left: $interiorMarginSm;
[class*="view-control"] {
padding: 2px 10px;
}
@include desktop {
&:hover {
background: $colorItemTreeHoverBg;
}
> * + * {
margin-left: ceil($interiorMarginSm / 2);
}
@include hover {
background: $colorItemTreeHoverBg;
}
// Object labels in trees

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,6 @@
<template>
<div
:style="{
'top': virtualScroll ? itemTop : 'auto',
'position': virtualScroll ? 'absolute' : 'relative'
}"
:style="treeItemStyles"
class="c-tree__item-h"
>
<div
@@ -17,28 +14,23 @@
@contextmenu.capture="handleContextMenu"
>
<view-control
ref="navUp"
v-model="expanded"
ref="navigate"
class="c-tree__item__view-control"
:control-class="'icon-arrow-nav-to-parent'"
:enabled="showUp"
@input="resetTreeHere"
:value="isOpen || isLoading"
:enabled="!activeSearch && hasComposition"
@input="navigationClick()"
/>
<object-label
ref="objectLabel"
:domain-object="node.object"
:object-path="node.objectPath"
:navigate-to-path="navigationPath"
:style="{ paddingLeft: leftOffset }"
@context-click-active="setContextClickActive"
/>
<view-control
ref="navDown"
v-model="expanded"
class="c-tree__item__view-control"
:control-class="'c-nav__down'"
:enabled="hasComposition && showDown"
/>
<span
v-if="isLoading"
class="loading"
></span>
</div>
</div>
</template>
@@ -59,17 +51,13 @@ export default {
type: Object,
required: true
},
leftOffset: {
type: String,
default: '0px'
},
showUp: {
activeSearch: {
type: Boolean,
default: false
},
showDown: {
type: Boolean,
default: true
leftOffset: {
type: String,
default: '0px'
},
itemIndex: {
type: Number,
@@ -86,9 +74,13 @@ export default {
required: false,
default: 0
},
virtualScroll: {
type: Boolean,
default: false
openItems: {
type: Array,
required: true
},
loadingItems: {
type: Object,
required: true
}
},
data() {
@@ -97,7 +89,6 @@ export default {
return {
hasComposition: false,
navigated: this.isNavigated(),
expanded: false,
contextClickActive: false
};
},
@@ -113,37 +104,44 @@ export default {
return parentKeyString !== this.node.object.location;
},
itemTop() {
return (this.itemOffset + this.itemIndex) * this.itemHeight + 'px';
}
},
watch: {
expanded() {
this.$emit('expanded', this.domainObject);
isLoading() {
return Boolean(this.loadingItems[this.navigationPath]);
},
isOpen() {
return this.openItems.includes(this.navigationPath);
},
treeItemStyles() {
let itemTop = (this.itemOffset + this.itemIndex) * this.itemHeight + 'px';
return {
'top': itemTop,
'position': 'absolute',
'padding-left': this.leftOffset
};
}
},
mounted() {
let objectComposition = this.openmct.composition.get(this.node.object);
this.domainObject = this.node.object;
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
this.domainObject = newObject;
});
this.$once('hook:destroyed', removeListener);
if (objectComposition) {
if (this.openmct.composition.get(this.domainObject)) {
this.hasComposition = true;
}
this.openmct.router.on('change:path', this.highlightIfNavigated);
this.$emit('tree-item-mounted', this.navigationPath);
},
destroyed() {
this.openmct.router.off('change:path', this.highlightIfNavigated);
this.$emit('tree-item-destoyed', this.navigationPath);
},
methods: {
navigationClick() {
this.$emit('navigation-click', this.isOpen || this.isLoading ? 'close' : 'open');
},
handleClick(event) {
// skip for navigation, let viewControl handle click
if ([this.$refs.navUp.$el, this.$refs.navDown.$el].includes(event.target)) {
if (this.$refs.navigate.$el === event.target) {
return;
}
@@ -160,9 +158,6 @@ export default {
highlightIfNavigated() {
this.navigated = this.isNavigated();
},
resetTreeHere() {
this.$emit('resetTree', this.node);
},
setContextClickActive(active) {
this.contextClickActive = active;
}

View File

@@ -64,27 +64,21 @@ const webpackConfig = {
filename: '[name].css',
chunkFilename: '[name].css'
}),
new CopyWebpackPlugin({
patterns: [
{
from: 'src/images/favicons',
to: 'favicons'
},
{
from: './index.html',
transform: function (content) {
return content.toString().replace(/dist\//g, '');
}
new CopyWebpackPlugin([
{
from: 'src/images/favicons',
to: 'favicons'
},
{
from: './index.html',
transform: function (content) {
return content.toString().replace(/dist\//g, '');
}
]
})
}
])
],
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.(sc|sa|c)ss$/,
use: [
@@ -124,14 +118,17 @@ const webpackConfig = {
}
}
},
{
test: /\.vue$/,
use: 'vue-loader'
}
]
},
ignoreWarnings: [/asset size limit/g],
stats: {
modules: false,
timings: true,
colors: true
colors: true,
warningsFilter: /asset size limit/g
}
};