mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 18:50:11 +00:00
Compare commits
44 Commits
recursive-
...
deep-plotl
Author | SHA1 | Date | |
---|---|---|---|
043d6aa9c3 | |||
ecfab8f7f3 | |||
05c38c37aa | |||
ce78925119 | |||
26aca0f433 | |||
41259bbd40 | |||
580640ff47 | |||
a4aec5d492 | |||
23303c910e | |||
00b3f3ac0b | |||
3282934cf6 | |||
c157fab081 | |||
7c07b66cc9 | |||
7a906ccf5c | |||
ff7debfb81 | |||
92ba103f45 | |||
2c2d8d6b56 | |||
cfadb9f4fd | |||
c185f77a15 | |||
0dff431f4a | |||
61d238a097 | |||
f9deb80350 | |||
021d730814 | |||
ae62b15abf | |||
ba41c1a30e | |||
b9a85d9c4d | |||
80eab8bad1 | |||
b2d8d640ae | |||
56e6fa66c2 | |||
9fa4707c82 | |||
7e2cfa36de | |||
aaa60a1545 | |||
717231fed2 | |||
7fb2bc9729 | |||
addeb635e9 | |||
608d63a7b0 | |||
10679e5f4f | |||
38b8f03b1a | |||
779a42c28c | |||
80c2504768 | |||
80359e3f16 | |||
66aa4f099f | |||
aa6c6cb88b | |||
4e5cc840d7 |
@ -20,8 +20,8 @@ jobs:
|
||||
paths:
|
||||
- node_modules
|
||||
- run:
|
||||
name: npm run test
|
||||
command: npm run test
|
||||
name: npm run test:coverage
|
||||
command: npm run test:coverage
|
||||
- run:
|
||||
name: npm run lint
|
||||
command: npm run lint
|
||||
|
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="example">{{ msg }}</div>
|
||||
<div class="example">{{ msg }}</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Hello world!'
|
||||
data() {
|
||||
return {
|
||||
msg: 'Hello world!'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -24,16 +24,27 @@
|
||||
|
||||
const devMode = process.env.NODE_ENV !== 'production';
|
||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless'];
|
||||
const coverageEnabled = process.env.COVERAGE === 'true';
|
||||
const reporters = ['progress', 'html'];
|
||||
|
||||
if (coverageEnabled) {
|
||||
reporters.push('coverage-istanbul');
|
||||
}
|
||||
|
||||
module.exports = (config) => {
|
||||
const webpackConfig = require('./webpack.config.js');
|
||||
delete webpackConfig.output;
|
||||
|
||||
if (!devMode) {
|
||||
if (!devMode || coverageEnabled) {
|
||||
webpackConfig.module.rules.push({
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules|example/,
|
||||
use: 'istanbul-instrumenter-loader'
|
||||
exclude: /node_modules|example|lib|dist/,
|
||||
use: {
|
||||
loader: 'istanbul-instrumenter-loader',
|
||||
options: {
|
||||
esModules: true
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -45,11 +56,7 @@ module.exports = (config) => {
|
||||
'src/**/*Spec.js'
|
||||
],
|
||||
port: 9876,
|
||||
reporters: [
|
||||
'progress',
|
||||
'coverage',
|
||||
'html'
|
||||
],
|
||||
reporters: reporters,
|
||||
browsers: browsers,
|
||||
customLaunchers: {
|
||||
ChromeDebugging: {
|
||||
@ -61,27 +68,27 @@ module.exports = (config) => {
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
coverageReporter: {
|
||||
dir: process.env.CIRCLE_ARTIFACTS ?
|
||||
process.env.CIRCLE_ARTIFACTS + '/coverage' :
|
||||
"dist/reports/coverage",
|
||||
check: {
|
||||
global: {
|
||||
lines: 80,
|
||||
excludes: ['src/plugins/plot/**/*.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
// HTML test reporting.
|
||||
htmlReporter: {
|
||||
outputDir: "dist/reports/tests",
|
||||
preserveDescribeNesting: true,
|
||||
foldAll: false
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
fixWebpackSourcePaths: true,
|
||||
dir: process.env.CIRCLE_ARTIFACTS ?
|
||||
process.env.CIRCLE_ARTIFACTS + '/coverage' :
|
||||
"dist/reports/coverage",
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
thresholds: {
|
||||
global: {
|
||||
lines: 62
|
||||
}
|
||||
}
|
||||
},
|
||||
preprocessors: {
|
||||
// add webpack as preprocessor
|
||||
'platform/**/*Spec.js': [ 'webpack', 'sourcemap' ],
|
||||
'src/**/*Spec.js': [ 'webpack', 'sourcemap' ]
|
||||
'platform/**/*Spec.js': ['webpack', 'sourcemap'],
|
||||
'src/**/*Spec.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
|
15
package.json
15
package.json
@ -2,7 +2,9 @@
|
||||
"name": "openmct",
|
||||
"version": "1.0.0-snapshot",
|
||||
"description": "The Open MCT core platform",
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"plotly.js-dist": "^1.54.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular": "1.7.9",
|
||||
"angular-route": "1.4.14",
|
||||
@ -42,6 +44,7 @@
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-cli": "^1.0.1",
|
||||
"karma-coverage": "^1.1.2",
|
||||
"karma-coverage-istanbul-reporter": "^2.1.1",
|
||||
"karma-html-reporter": "^0.2.7",
|
||||
"karma-jasmine": "^1.1.2",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
@ -52,7 +55,7 @@
|
||||
"marked": "^0.3.5",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
"minimist": "^1.1.1",
|
||||
"moment": "^2.11.1",
|
||||
"moment": "^2.25.3",
|
||||
"moment-duration-format": "^2.2.2",
|
||||
"moment-timezone": "^0.5.21",
|
||||
"node-bourbon": "^4.2.3",
|
||||
@ -75,14 +78,16 @@
|
||||
"zepto": "^1.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rm -rf ./dist",
|
||||
"start": "node app.js",
|
||||
"lint": "eslint platform example src/**/*.{js,vue} openmct.js",
|
||||
"lint:fix": "eslint platform example src/**/*.{js,vue} openmct.js --fix",
|
||||
"lint": "eslint platform example src --ext .js,.vue openmct.js",
|
||||
"lint:fix": "eslint platform example src --ext .js,.vue openmct.js --fix",
|
||||
"build:prod": "cross-env NODE_ENV=production webpack",
|
||||
"build:dev": "webpack",
|
||||
"build:watch": "webpack --watch",
|
||||
"test": "karma start --single-run",
|
||||
"test-debug": "cross-env NODE_ENV=debug karma start --no-single-run",
|
||||
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
|
||||
"test:coverage": "./scripts/test-coverage.sh",
|
||||
"test:watch": "karma start --no-single-run",
|
||||
"verify": "concurrently 'npm:test' 'npm:lint'",
|
||||
"jsdoc": "jsdoc -c jsdoc.json -R API.md -r -d dist/docs/api",
|
||||
|
2
scripts/test-coverage.sh
Executable file
2
scripts/test-coverage.sh
Executable file
@ -0,0 +1,2 @@
|
||||
export NODE_OPTIONS=--max_old_space_size=4096
|
||||
cross-env COVERAGE=true karma start --single-run
|
@ -252,6 +252,7 @@ define([
|
||||
// Plugin's that are installed by default
|
||||
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.PlotlyPlot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
this.install(PreviewPlugin.default());
|
||||
this.install(LegacyIndicatorsPlugin());
|
||||
|
@ -69,7 +69,6 @@ export default class ConditionClass extends EventEmitter {
|
||||
console.log('no data received');
|
||||
return;
|
||||
}
|
||||
|
||||
this.criteria.forEach(criterion => {
|
||||
if (this.isAnyOrAllTelemetry(criterion)) {
|
||||
criterion.getResult(datum, this.conditionManager.telemetryObjects);
|
||||
|
@ -57,6 +57,7 @@ export default class ConditionManager extends EventEmitter {
|
||||
endpoint,
|
||||
this.telemetryReceived.bind(this, endpoint)
|
||||
);
|
||||
// TODO check if this is needed
|
||||
this.updateConditionTelemetry();
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,13 @@
|
||||
import EventEmitter from 'EventEmitter';
|
||||
|
||||
export default class StyleRuleManager extends EventEmitter {
|
||||
constructor(styleConfiguration, openmct, callback) {
|
||||
constructor(styleConfiguration, openmct, callback, suppressSubscriptionOnEdit) {
|
||||
super();
|
||||
this.openmct = openmct;
|
||||
this.callback = callback;
|
||||
if (suppressSubscriptionOnEdit) {
|
||||
this.openmct.editor.on('isEditing', this.toggleSubscription.bind(this));
|
||||
}
|
||||
if (styleConfiguration) {
|
||||
this.initialize(styleConfiguration);
|
||||
if (styleConfiguration.conditionSetIdentifier) {
|
||||
@ -37,9 +40,25 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
toggleSubscription(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
if (this.isEditing) {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
if (this.conditionSetIdentifier) {
|
||||
this.applySelectedConditionStyle();
|
||||
}
|
||||
} else if (this.conditionSetIdentifier) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
}
|
||||
|
||||
initialize(styleConfiguration) {
|
||||
this.conditionSetIdentifier = styleConfiguration.conditionSetIdentifier;
|
||||
this.staticStyle = styleConfiguration.staticStyle;
|
||||
this.selectedConditionId = styleConfiguration.selectedConditionId;
|
||||
this.defaultConditionId = styleConfiguration.defaultConditionId;
|
||||
this.updateConditionStylesMap(styleConfiguration.styles || []);
|
||||
}
|
||||
|
||||
@ -54,7 +73,7 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
this.handleConditionSetResultUpdated(output[0]);
|
||||
}
|
||||
});
|
||||
this.stopProvidingTelemetry = this.openmct.telemetry.subscribe(conditionSetDomainObject, output => this.handleConditionSetResultUpdated(output));
|
||||
this.stopProvidingTelemetry = this.openmct.telemetry.subscribe(conditionSetDomainObject, this.handleConditionSetResultUpdated.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
@ -66,9 +85,13 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
let isNewConditionSet = !this.conditionSetIdentifier ||
|
||||
!this.openmct.objects.areIdsEqual(this.conditionSetIdentifier, styleConfiguration.conditionSetIdentifier);
|
||||
this.initialize(styleConfiguration);
|
||||
//Only resubscribe if the conditionSet has changed.
|
||||
if (isNewConditionSet) {
|
||||
this.subscribeToConditionSet();
|
||||
if (this.isEditing) {
|
||||
this.applySelectedConditionStyle();
|
||||
} else {
|
||||
//Only resubscribe if the conditionSet has changed.
|
||||
if (isNewConditionSet) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,6 +126,16 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
applySelectedConditionStyle() {
|
||||
const conditionId = this.selectedConditionId || this.defaultConditionId;
|
||||
if (!conditionId) {
|
||||
this.applyStaticStyle();
|
||||
} else if (this.conditionalStyleMap[conditionId]) {
|
||||
this.currentStyle = this.conditionalStyleMap[conditionId];
|
||||
this.updateDomainObjectStyle();
|
||||
}
|
||||
}
|
||||
|
||||
applyStaticStyle() {
|
||||
if (this.staticStyle) {
|
||||
this.currentStyle = this.staticStyle.style;
|
||||
@ -123,6 +156,8 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
}
|
||||
delete this.stopProvidingTelemetry;
|
||||
this.conditionSetIdentifier = undefined;
|
||||
this.isEditing = undefined;
|
||||
this.callback = undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -79,6 +79,8 @@
|
||||
<div v-for="(conditionStyle, index) in conditionalStyles"
|
||||
:key="index"
|
||||
class="c-inspect-styles__condition"
|
||||
:class="{'is-current': conditionStyle.conditionId === selectedConditionId}"
|
||||
@click="applySelectedConditionStyle(conditionStyle.conditionId)"
|
||||
>
|
||||
<condition-error :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
@ -126,7 +128,8 @@ export default {
|
||||
isEditing: this.openmct.editor.isEditing(),
|
||||
conditions: undefined,
|
||||
conditionsLoaded: false,
|
||||
navigateToPath: ''
|
||||
navigateToPath: '',
|
||||
selectedConditionId: ''
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
@ -191,6 +194,9 @@ export default {
|
||||
if (this.stopObservingItems) {
|
||||
this.stopObservingItems();
|
||||
}
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
},
|
||||
initialize(conditionSetDomainObject) {
|
||||
//If there are new conditions in the conditionSet we need to set those styles to default
|
||||
@ -200,6 +206,13 @@ export default {
|
||||
},
|
||||
setEditState(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
if (this.isEditing) {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
} else {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
addConditionSet() {
|
||||
let conditionSetDomainObject;
|
||||
@ -270,6 +283,8 @@ export default {
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
if (this.itemId) {
|
||||
domainObjectStyles[this.itemId].conditionSetIdentifier = undefined;
|
||||
domainObjectStyles[this.itemId].selectedConditionId = undefined;
|
||||
domainObjectStyles[this.itemId].defaultConditionId = undefined;
|
||||
delete domainObjectStyles[this.itemId].conditionSetIdentifier;
|
||||
domainObjectStyles[this.itemId].styles = undefined;
|
||||
delete domainObjectStyles[this.itemId].styles;
|
||||
@ -278,6 +293,8 @@ export default {
|
||||
}
|
||||
} else {
|
||||
domainObjectStyles.conditionSetIdentifier = undefined;
|
||||
domainObjectStyles.selectedConditionId = undefined;
|
||||
domainObjectStyles.defaultConditionId = undefined;
|
||||
delete domainObjectStyles.conditionSetIdentifier;
|
||||
domainObjectStyles.styles = undefined;
|
||||
delete domainObjectStyles.styles;
|
||||
@ -287,16 +304,23 @@ export default {
|
||||
}
|
||||
|
||||
this.persist(domainObjectStyles);
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
},
|
||||
updateDomainObjectItemStyles(newItems) {
|
||||
//check that all items that have been styles still exist. Otherwise delete those styles
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
let itemsToRemove = [];
|
||||
let keys = Object.keys(domainObjectStyles);
|
||||
//TODO: Need an easier way to find which properties are itemIds
|
||||
keys.forEach((key) => {
|
||||
if ((key !== 'styles') &&
|
||||
const keyIsItemId = (key !== 'styles') &&
|
||||
(key !== 'staticStyle') &&
|
||||
(key !== 'conditionSetIdentifier')) {
|
||||
(key !== 'defaultConditionId') &&
|
||||
(key !== 'selectedConditionId') &&
|
||||
(key !== 'conditionSetIdentifier');
|
||||
if (keyIsItemId) {
|
||||
if (!(newItems.find(item => item.id === key))) {
|
||||
itemsToRemove.push(key);
|
||||
}
|
||||
@ -324,6 +348,9 @@ export default {
|
||||
}
|
||||
let conditionalStyles = [];
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
|
||||
if (conditionConfiguration.isDefault) {
|
||||
this.selectedConditionId = conditionConfiguration.id;
|
||||
}
|
||||
this.conditions[conditionConfiguration.id] = conditionConfiguration;
|
||||
let foundStyle = this.findStyleByConditionId(conditionConfiguration.id);
|
||||
if (foundStyle) {
|
||||
@ -339,7 +366,27 @@ export default {
|
||||
//we're doing this so that we remove styles for any conditions that have been removed from the condition set
|
||||
this.conditionalStyles = conditionalStyles;
|
||||
this.conditionsLoaded = true;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
this.persist(this.getDomainObjectConditionalStyle(this.selectedConditionId));
|
||||
if (!this.isEditing) {
|
||||
this.subscribeToConditionSet();
|
||||
}
|
||||
},
|
||||
subscribeToConditionSet() {
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
if (this.conditionSetDomainObject) {
|
||||
this.openmct.telemetry.request(this.conditionSetDomainObject)
|
||||
.then(output => {
|
||||
if (output && output.length) {
|
||||
this.handleConditionSetResultUpdated(output[0]);
|
||||
}
|
||||
});
|
||||
this.stopProvidingTelemetry = this.openmct.telemetry.subscribe(this.conditionSetDomainObject, this.handleConditionSetResultUpdated.bind(this));
|
||||
}
|
||||
},
|
||||
handleConditionSetResultUpdated(resultData) {
|
||||
this.selectedConditionId = resultData ? resultData.conditionId : '';
|
||||
},
|
||||
initializeStaticStyle(objectStyles) {
|
||||
let staticStyle = objectStyles && objectStyles.staticStyle;
|
||||
@ -364,14 +411,19 @@ export default {
|
||||
let found = this.findStyleByConditionId(conditionStyle.conditionId);
|
||||
if (found) {
|
||||
found.style = conditionStyle.style;
|
||||
this.selectedConditionId = found.conditionId;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
}
|
||||
},
|
||||
getDomainObjectConditionalStyle() {
|
||||
getDomainObjectConditionalStyle(defaultConditionId) {
|
||||
let objectStyle = {
|
||||
styles: this.conditionalStyles,
|
||||
staticStyle: this.staticStyle
|
||||
staticStyle: this.staticStyle,
|
||||
selectedConditionId: this.selectedConditionId
|
||||
};
|
||||
if (defaultConditionId) {
|
||||
objectStyle.defaultConditionId = defaultConditionId;
|
||||
}
|
||||
if (this.conditionSetDomainObject) {
|
||||
objectStyle.conditionSetIdentifier = this.conditionSetDomainObject.identifier;
|
||||
}
|
||||
@ -393,6 +445,10 @@ export default {
|
||||
getCondition(id) {
|
||||
return this.conditions ? this.conditions[id] : {};
|
||||
},
|
||||
applySelectedConditionStyle(conditionId) {
|
||||
this.selectedConditionId = conditionId;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
},
|
||||
persist(style) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration.objectStyles', style);
|
||||
}
|
||||
|
@ -60,6 +60,31 @@
|
||||
|
||||
&__condition {
|
||||
@include discreteItem();
|
||||
border: 1px solid transparent;
|
||||
pointer-events: none; // Prevent selecting when the object isn't being edited
|
||||
|
||||
&.is-current {
|
||||
$c: $colorBodyFg;
|
||||
border-color: rgba($c, 0.5);
|
||||
background: rgba($c, 0.2);
|
||||
}
|
||||
|
||||
.is-editing & {
|
||||
cursor: pointer;
|
||||
pointer-events: initial;
|
||||
transition: $transOut;
|
||||
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, 0.1);
|
||||
transition: $transIn;
|
||||
}
|
||||
|
||||
&.is-current {
|
||||
$c: $editUIColorBg;
|
||||
border-color: $c;
|
||||
background: rgba($c, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-style {
|
||||
|
@ -52,7 +52,7 @@ export default {
|
||||
},
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager(this.objectStyle, this.openmct, this.updateStyle.bind(this));
|
||||
this.styleRuleManager = new StyleRuleManager(this.objectStyle, this.openmct, this.updateStyle.bind(this), true);
|
||||
} else {
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
|
||||
}
|
||||
|
@ -162,19 +162,31 @@ export default {
|
||||
}).show(this.embed.snapshot.src);
|
||||
},
|
||||
changeLocation() {
|
||||
this.openmct.time.stopClock();
|
||||
this.openmct.time.bounds({
|
||||
start: this.embed.bounds.start,
|
||||
end: this.embed.bounds.end
|
||||
});
|
||||
|
||||
const link = this.embed.historicLink;
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bounds = this.openmct.time.bounds();
|
||||
const isTimeBoundChanged = this.embed.bounds.start !== bounds.start
|
||||
&& this.embed.bounds.end !== bounds.end;
|
||||
const isFixedTimespanMode = !this.openmct.time.clock();
|
||||
|
||||
window.location.href = link;
|
||||
const message = 'Time bounds changed to fixed timespan mode';
|
||||
|
||||
let message = '';
|
||||
if (isTimeBoundChanged) {
|
||||
this.openmct.time.bounds({
|
||||
start: this.embed.bounds.start,
|
||||
end: this.embed.bounds.end
|
||||
});
|
||||
message = 'Time bound values changed';
|
||||
}
|
||||
|
||||
if (!isFixedTimespanMode) {
|
||||
message = 'Time bound values changed to fixed timespan mode';
|
||||
}
|
||||
|
||||
this.openmct.notifications.alert(message);
|
||||
},
|
||||
formatTime(unixTime, timeFormat) {
|
||||
|
@ -221,7 +221,7 @@ export default {
|
||||
return position;
|
||||
},
|
||||
formatTime(unixTime, timeFormat) {
|
||||
return Moment(unixTime).format(timeFormat);
|
||||
return Moment.utc(unixTime).format(timeFormat);
|
||||
},
|
||||
moveSnapshot(snapshotId) {
|
||||
const snapshot = this.snapshotContainer.getSnapshot(snapshotId);
|
||||
|
@ -40,6 +40,18 @@ export default {
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
ignoreLink: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
objectPath: {
|
||||
type: Array,
|
||||
default() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -97,17 +109,27 @@ export default {
|
||||
this.showMenu = false;
|
||||
},
|
||||
snapshot(notebook) {
|
||||
let element = document.getElementsByClassName("l-shell__main-container")[0];
|
||||
const bounds = this.openmct.time.bounds();
|
||||
const objectPath = this.openmct.router.path;
|
||||
const snapshotMeta = {
|
||||
bounds,
|
||||
link: window.location.href,
|
||||
objectPath,
|
||||
openmct: this.openmct
|
||||
};
|
||||
this.hideMenu();
|
||||
|
||||
this.notebookSnapshot.capture(snapshotMeta, notebook.type, element);
|
||||
this.$nextTick(() => {
|
||||
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.href
|
||||
: null;
|
||||
|
||||
const objectPath = this.objectPath || this.openmct.router.path;
|
||||
const snapshotMeta = {
|
||||
bounds,
|
||||
link,
|
||||
objectPath,
|
||||
openmct: this.openmct
|
||||
};
|
||||
|
||||
this.notebookSnapshot.capture(snapshotMeta, notebook.type, element);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +495,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (section.id !== defaultNotebookSection.id) {
|
||||
if (id !== defaultNotebookSection.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
-->
|
||||
<div ng-controller="StackedPlotController as stackedPlot"
|
||||
class="c-plot c-plot--stacked holder holder-plot has-control-bar">
|
||||
<div class="l-control-bar" ng-show="!stackedPlot.hideExportButtons">
|
||||
<div class="c-control-bar" ng-show="!stackedPlot.hideExportButtons">
|
||||
<span class="c-button-set c-button-set--strip-h">
|
||||
<button class="c-button icon-download"
|
||||
ng-click="stackedPlot.exportPNG()"
|
||||
|
@ -81,7 +81,8 @@ define(
|
||||
clonedElement.classList.add(className);
|
||||
}
|
||||
element.id = oldId;
|
||||
}
|
||||
},
|
||||
removeContainer: true // Set to false to debug what html2canvas renders
|
||||
}).then(function (canvas) {
|
||||
dialog.dismiss();
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
35
src/plugins/plotlyPlot/PlotlyTelemetryProvider.js
Normal file
35
src/plugins/plotlyPlot/PlotlyTelemetryProvider.js
Normal file
@ -0,0 +1,35 @@
|
||||
export default class PlotlyTelemetryProvider {
|
||||
constructor(openmct) {
|
||||
this.openmct = openmct;
|
||||
}
|
||||
|
||||
isTelemetryObject(domainObject) {
|
||||
return domainObject.type === 'plotlyPlot';
|
||||
}
|
||||
|
||||
supportsRequest(domainObject) {
|
||||
return domainObject.type === 'plotlyPlot';
|
||||
}
|
||||
|
||||
supportsSubscribe(domainObject) {
|
||||
return domainObject.type === 'plotlyPlot';
|
||||
}
|
||||
|
||||
request(domainObject) {
|
||||
// let conditionManager = this.getConditionManager(domainObject);
|
||||
|
||||
// return conditionManager.requestLADConditionSetOutput()
|
||||
// .then(latestOutput => {
|
||||
// return latestOutput;
|
||||
// });
|
||||
}
|
||||
|
||||
subscribe(domainObject, callback) {
|
||||
// let conditionManager = this.getConditionManager(domainObject);
|
||||
|
||||
// conditionManager.on('conditionSetResultUpdated', callback);
|
||||
|
||||
// return this.destroyConditionManager.bind(this, this.openmct.objects.makeKeyString(domainObject.identifier));
|
||||
}
|
||||
|
||||
}
|
73
src/plugins/plotlyPlot/PlotlyViewProvider.js
Normal file
73
src/plugins/plotlyPlot/PlotlyViewProvider.js
Normal file
@ -0,0 +1,73 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2019, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* 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 PlotlyViewLayout from './components/PlotlyViewLayout.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
export default function PlotlyViewProvider(openmct) {
|
||||
return {
|
||||
key: 'plotlyPlot',
|
||||
name: 'Plotly Plot',
|
||||
cssClass: 'icon-plot-overlay',
|
||||
canView: function (domainObject) {
|
||||
return domainObject.type === 'plotlyPlot';
|
||||
},
|
||||
canEdit: function (domainObject) {
|
||||
return domainObject.type === 'plotlyPlot';
|
||||
},
|
||||
view: function (domainObject, objectPath) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element, isEditing) {
|
||||
component = new Vue({
|
||||
provide: {
|
||||
openmct,
|
||||
domainObject,
|
||||
objectPath
|
||||
},
|
||||
el: element,
|
||||
components: {
|
||||
PlotlyViewLayout
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing
|
||||
}
|
||||
},
|
||||
template: '<plotly-view-layout :isEditing="isEditing"></plotly-view-layout>'
|
||||
});
|
||||
},
|
||||
onEditModeChange: function (isEditing) {
|
||||
component.isEditing = isEditing;
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
};
|
||||
},
|
||||
priority: function () {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
138
src/plugins/plotlyPlot/components/PlotlyViewLayout.vue
Normal file
138
src/plugins/plotlyPlot/components/PlotlyViewLayout.vue
Normal file
@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<div class="l-view-section"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Plotly from 'plotly.js-dist';
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'domainObject', 'objectPath'],
|
||||
data: function () {
|
||||
|
||||
return {
|
||||
telemetryObjects: []
|
||||
// currentDomainObject: this.domainObject
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addTelemetry);
|
||||
this.composition.load();
|
||||
|
||||
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
||||
|
||||
console.log('this.metadata', this.metadata);
|
||||
|
||||
// this.keystring = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||
// this.subscribe(this.domainObject);
|
||||
this.plotElement = document.querySelector('.l-view-section');
|
||||
// Plotly.newPlot(this.plotElement, [{
|
||||
// x: [1, 2, 3, 4, 5],
|
||||
// y: [1, 2, 4, 8, 16]
|
||||
// }], this.getLayout(), {displayModeBar: false});
|
||||
|
||||
},
|
||||
methods: {
|
||||
getLayout() {
|
||||
return {
|
||||
hovermode: 'compare',
|
||||
hoverdistance: -1,
|
||||
autosize: "true",
|
||||
showlegend: false,
|
||||
font: {
|
||||
family: "'Helvetica Neue', Helvetica, Arial, sans-serif",
|
||||
size: "12px",
|
||||
color: "#666"
|
||||
},
|
||||
xaxis: {
|
||||
// title: this.plotAxisTitle.xAxisTitle,
|
||||
zeroline: false
|
||||
},
|
||||
yaxis: {
|
||||
// title: this.plotAxisTitle.yAxisTitle,
|
||||
zeroline: false
|
||||
},
|
||||
margin: {
|
||||
l: 20,
|
||||
r: 10,
|
||||
b: 20,
|
||||
t: 10
|
||||
},
|
||||
paper_bgcolor: 'transparent',
|
||||
plot_bgcolor: 'transparent'
|
||||
}
|
||||
},
|
||||
addTelemetry(telemetryObject) {
|
||||
return this.openmct.telemetry.request(telemetryObject)
|
||||
.then(telemetryData => {
|
||||
this.createPlot(telemetryData, telemetryObject);
|
||||
}, () => {console.log(error)});
|
||||
},
|
||||
formatDatumX(datum) {
|
||||
let timestamp = moment.utc(datum.utc).format('YYYY-MM-DD hh:mm:ss.ms');
|
||||
return timestamp;
|
||||
},
|
||||
formatDatumY(datum) {
|
||||
return datum.sin;
|
||||
},
|
||||
createPlot(telemetryData, telemetryObject) {
|
||||
let x = [],
|
||||
y = [];
|
||||
|
||||
telemetryData.forEach((datum, index) => {
|
||||
x.push(this.formatDatumX(datum));
|
||||
y.push(this.formatDatumY(datum));
|
||||
})
|
||||
|
||||
let data = [{
|
||||
x,
|
||||
y,
|
||||
mode: 'line'
|
||||
}];
|
||||
var layout = {
|
||||
title:'Line and Scatter Plot'
|
||||
};
|
||||
Plotly.newPlot(
|
||||
this.plotElement,
|
||||
data,
|
||||
this.getLayout()
|
||||
)
|
||||
|
||||
this.subscribe(telemetryObject);
|
||||
},
|
||||
subscribe(domainObject) {
|
||||
// this.date = ''
|
||||
// this.openmct.objects.get(this.keystring)
|
||||
// .then((object) => {
|
||||
// const metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
||||
// console.log('metadata', metadata);
|
||||
// // this.timeKey = this.openmct.time.timeSystem().key;
|
||||
// // this.timeFormat = this.openmct.telemetry.getValueFormatter(metadata.value(this.timeKey));
|
||||
// // // this.imageFormat = this.openmct.telemetry.getValueFormatter(metadata.valuesForHints(['image'])[0]);
|
||||
// // this.unsubscribe = this.openmct.telemetry
|
||||
// // .subscribe(this.domainObject, (datum) => {
|
||||
// // this.updateHistory(datum);
|
||||
// // this.updateValues(datum);
|
||||
// // });
|
||||
|
||||
// // this.requestHistory(this.openmct.time.bounds());
|
||||
// });
|
||||
|
||||
this.openmct.telemetry.subscribe(domainObject, (datum) => {
|
||||
this.updateData(datum)
|
||||
})
|
||||
},
|
||||
updateData(datum) {
|
||||
Plotly.extendTraces(
|
||||
this.plotElement,
|
||||
{
|
||||
x: [[this.formatDatumX(datum)]],
|
||||
y: [[this.formatDatumY(datum)]]
|
||||
},
|
||||
[0]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
src/plugins/plotlyPlot/components/plotly.scss
Normal file
2
src/plugins/plotlyPlot/components/plotly.scss
Normal file
@ -0,0 +1,2 @@
|
||||
.plot svg {
|
||||
}
|
20
src/plugins/plotlyPlot/plugin.js
Normal file
20
src/plugins/plotlyPlot/plugin.js
Normal file
@ -0,0 +1,20 @@
|
||||
import PlotlyViewProvider from './PlotlyViewProvider.js';
|
||||
import PlotlyTelemetryProvider from './PlotlyTelemetryProvider.js';
|
||||
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
openmct.objectViews.addProvider(new PlotlyViewProvider(openmct));
|
||||
openmct.telemetry.addProvider(new PlotlyTelemetryProvider(openmct));
|
||||
|
||||
openmct.types.addType('plotlyPlot', {
|
||||
name: "Plotly Plot",
|
||||
description: "Simple plot rendered by plotly.js",
|
||||
creatable: true,
|
||||
cssClass: 'icon-plot-overlay',
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
domainObject.telemetry = {};
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
@ -34,6 +34,7 @@ define([
|
||||
'./URLIndicatorPlugin/URLIndicatorPlugin',
|
||||
'./telemetryMean/plugin',
|
||||
'./plot/plugin',
|
||||
'./plotlyPlot/plugin',
|
||||
'./telemetryTable/plugin',
|
||||
'./staticRootPlugin/plugin',
|
||||
'./notebook/plugin',
|
||||
@ -66,6 +67,7 @@ define([
|
||||
URLIndicatorPlugin,
|
||||
TelemetryMean,
|
||||
PlotPlugin,
|
||||
PlotlyPlotPlugin,
|
||||
TelemetryTablePlugin,
|
||||
StaticRootPlugin,
|
||||
Notebook,
|
||||
@ -171,8 +173,8 @@ define([
|
||||
plugins.ExampleImagery = ExampleImagery;
|
||||
plugins.ImageryPlugin = ImageryPlugin;
|
||||
plugins.Plot = PlotPlugin;
|
||||
plugins.PlotlyPlot = PlotlyPlotPlugin.default;
|
||||
plugins.TelemetryTable = TelemetryTablePlugin;
|
||||
|
||||
plugins.SummaryWidget = SummaryWidget;
|
||||
plugins.TelemetryMean = TelemetryMean;
|
||||
plugins.URLIndicator = URLIndicatorPlugin;
|
||||
|
@ -165,7 +165,16 @@
|
||||
/******************************* LEGACY */
|
||||
.s-status-taking-snapshot,
|
||||
.overlay.snapshot {
|
||||
// Handle overflow-y issues with tables and html2canvas
|
||||
// Replaces .l-sticky-headers .l-tabular-body { overflow: auto; }
|
||||
.c-table__body-w { overflow: auto; }
|
||||
.c-table {
|
||||
&__body-w {
|
||||
overflow: auto; // Handle overflow-y issues with tables and html2canvas
|
||||
}
|
||||
|
||||
&-control-bar {
|
||||
display: none;
|
||||
+ * {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -565,6 +565,20 @@ select {
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************** CONTROL BARS */
|
||||
.c-control-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * + * {
|
||||
margin-left: $interiorMarginSm;
|
||||
}
|
||||
|
||||
&__label {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** PALETTES */
|
||||
.c-palette {
|
||||
|
@ -40,28 +40,58 @@ mct-plot {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-plot,
|
||||
.gl-plot {
|
||||
.s-status-taking-snapshot & {
|
||||
.c-control-bar {
|
||||
display: none;
|
||||
}
|
||||
.gl-plot-y-label__select {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-plot {
|
||||
$p: $mainViewPad;
|
||||
position: absolute;
|
||||
top: $p; right: $p; bottom: $p; left: $p;
|
||||
//$p: $mainViewPad;
|
||||
@include abs($mainViewPad);
|
||||
//position: absolute;
|
||||
//top: $p; right: $p; bottom: $p; left: $p;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> * + * {
|
||||
margin-top: $interiorMargin;
|
||||
}
|
||||
|
||||
.l-control-bar {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.l-view-section {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&--stacked {
|
||||
.l-view-section {
|
||||
// Make this a flex container
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
.gl-plot.child-frame {
|
||||
mct-plot {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
flex: 1 1 auto;
|
||||
&:not(:first-child) {
|
||||
margin-top: $interiorMargin;
|
||||
.child-frame {
|
||||
.has-control-bar {
|
||||
.c-control-bar {
|
||||
// Hides buttons per plot element in a stacked plot
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
mct-plot {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.s-status-timeconductor-unsynced .holder-plot {
|
||||
@ -70,7 +100,6 @@ mct-plot {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -186,7 +215,7 @@ mct-plot {
|
||||
left: 0; top: 0; right: auto; bottom: 0;
|
||||
padding-left: 5px;
|
||||
text-orientation: mixed;
|
||||
overflow: hidden;
|
||||
//overflow: hidden;
|
||||
writing-mode: vertical-lr;
|
||||
&:before {
|
||||
// Icon denoting configurability
|
||||
@ -339,11 +368,11 @@ mct-plot {
|
||||
z-index: -10;
|
||||
|
||||
.l-view-section {
|
||||
$m: $interiorMargin;
|
||||
top: $m !important;
|
||||
right: $m;
|
||||
bottom: $m;
|
||||
left: $m;
|
||||
//$m: $interiorMargin;
|
||||
//top: $m !important;
|
||||
//right: $m;
|
||||
//bottom: $m;
|
||||
//left: $m;
|
||||
|
||||
.s-status-timeconductor-unsynced .holder-plot {
|
||||
.t-object-alert.t-alert-unsynced {
|
||||
|
@ -19,53 +19,6 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/******************************************************************* VIEWS */
|
||||
// From _views.scss
|
||||
// Legacy overlay and stacked plots depend on this for now
|
||||
// Styles for sub-dividing views generically
|
||||
.l-control-bar {
|
||||
// Element that can be placed above l-view-section, holds controls, buttons, etc.
|
||||
height: $controlBarH;
|
||||
}
|
||||
|
||||
.c-control-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * + * {
|
||||
margin-left: $interiorMarginSm;
|
||||
}
|
||||
|
||||
&__label {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.l-view-section {
|
||||
@include abs();
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.has-control-bar {
|
||||
.l-view-section {
|
||||
top: $controlBarH + $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
.child-frame {
|
||||
.has-control-bar {
|
||||
.l-control-bar,
|
||||
.c-control-bar {
|
||||
// Hides buttons per plot element in a stacked plot
|
||||
display: none;
|
||||
}
|
||||
.l-view-section {
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************** CLOCKS AND TIMERS */
|
||||
.c-clock,
|
||||
.c-timer {
|
||||
|
@ -388,7 +388,21 @@
|
||||
.s-status-taking-snapshot,
|
||||
.overlay.snapshot {
|
||||
// Handle overflow-y issues with tables and html2canvas
|
||||
background: $colorBodyBg; // Prevent html2canvas from using white background
|
||||
color: $colorBodyFg;
|
||||
padding: $interiorMarginSm !important; // Prevents items from going right to the edge of the image
|
||||
|
||||
.l-sticky-headers .l-tabular-body { overflow: auto; }
|
||||
.l-browse-bar {
|
||||
display: none; // Suppress browse-bar when snapshotting from view-large overlay
|
||||
+ * {
|
||||
margin-top: 0 !important; // Remove margin from any following elements
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
box-shadow: none !important; // Prevent html2canvas problems with box-shadow
|
||||
}
|
||||
}
|
||||
|
||||
.c-notebook-snapshot {
|
||||
|
@ -18,6 +18,7 @@
|
||||
@import "../plugins/folderView/components/list-item.scss";
|
||||
@import "../plugins/folderView/components/list-view.scss";
|
||||
@import "../plugins/imagery/components/imagery-view-layout.scss";
|
||||
@import "../plugins/plotlyPlot/components/plotly.scss";
|
||||
@import "../plugins/telemetryTable/components/table-row.scss";
|
||||
@import "../plugins/telemetryTable/components/telemetry-filter-indicator.scss";
|
||||
@import "../plugins/tabs/components/tabs.scss";
|
||||
|
@ -59,6 +59,8 @@
|
||||
<script>
|
||||
import ObjectView from './ObjectView.vue'
|
||||
import ContextMenuDropDown from './contextMenuDropDown.vue';
|
||||
import PreviewHeader from '@/ui/preview/preview-header.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
const SIMPLE_CONTENT_TYPES = [
|
||||
'clock',
|
||||
@ -116,13 +118,41 @@ export default {
|
||||
childElement = parentElement.children[0];
|
||||
|
||||
this.openmct.overlays.overlay({
|
||||
element: childElement,
|
||||
element: this.getOverlayElement(childElement),
|
||||
size: 'large',
|
||||
onDestroy() {
|
||||
parentElement.append(childElement);
|
||||
}
|
||||
});
|
||||
},
|
||||
getOverlayElement(childElement) {
|
||||
const fragment = new DocumentFragment();
|
||||
const header = this.getPreviewHeader();
|
||||
fragment.append(header);
|
||||
fragment.append(childElement);
|
||||
|
||||
return fragment;
|
||||
},
|
||||
getPreviewHeader() {
|
||||
const domainObject = this.objectPath[0];
|
||||
const preview = new Vue({
|
||||
components: {
|
||||
PreviewHeader
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
objectPath: this.objectPath
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject
|
||||
}
|
||||
},
|
||||
template: '<PreviewHeader :domainObject="domainObject" :hideViewSwitcher="true" :showNotebookMenuSwitcher="true"></PreviewHeader>'
|
||||
});
|
||||
|
||||
return preview.$mount().$el;
|
||||
},
|
||||
getSelectionContext() {
|
||||
return this.$refs.objectView.getSelectionContext();
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ export default {
|
||||
},
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager((this.currentObject.configuration && this.currentObject.configuration.objectStyles), this.openmct, this.updateStyle.bind(this));
|
||||
this.styleRuleManager = new StyleRuleManager((this.currentObject.configuration && this.currentObject.configuration.objectStyles), this.openmct, this.updateStyle.bind(this), true);
|
||||
} else {
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.currentObject.configuration && this.currentObject.configuration.objectStyles);
|
||||
}
|
||||
|
@ -23,9 +23,12 @@
|
||||
}
|
||||
|
||||
&:not(.c-so-view--no-frame) {
|
||||
background: $colorBodyBg;
|
||||
border: $browseFrameBorder;
|
||||
padding: $interiorMargin;
|
||||
|
||||
.is-editing & {
|
||||
background: rgba($colorBodyBg, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
&--no-frame {
|
||||
|
@ -36,6 +36,7 @@
|
||||
<!-- Action buttons -->
|
||||
<NotebookMenuSwitcher v-if="notebookEnabled"
|
||||
:domain-object="domainObject"
|
||||
:object-path="openmct.router.path"
|
||||
class="c-notebook-snapshot-menubutton"
|
||||
/>
|
||||
<div class="l-browse-bar__actions">
|
||||
|
@ -21,28 +21,12 @@
|
||||
*****************************************************************************/
|
||||
<template>
|
||||
<div class="l-preview-window">
|
||||
<div class="l-browse-bar">
|
||||
<div class="l-browse-bar__start">
|
||||
<div
|
||||
class="l-browse-bar__object-name--w"
|
||||
:class="type.cssClass"
|
||||
>
|
||||
<span class="l-browse-bar__object-name">
|
||||
{{ domainObject.name }}
|
||||
</span>
|
||||
<context-menu-drop-down :object-path="objectPath" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="l-browse-bar__end">
|
||||
<div class="l-browse-bar__actions">
|
||||
<view-switcher
|
||||
:views="views"
|
||||
:current-view="currentView"
|
||||
@setView="setView"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<PreviewHeader
|
||||
:current-view="currentView"
|
||||
:domain-object="domainObject"
|
||||
:views="views"
|
||||
@setView="setView"
|
||||
/>
|
||||
<div class="l-preview-window__object-view">
|
||||
<div ref="objectView"></div>
|
||||
</div>
|
||||
@ -50,13 +34,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContextMenuDropDown from '../../ui/components/contextMenuDropDown.vue';
|
||||
import ViewSwitcher from '../../ui/layout/ViewSwitcher.vue';
|
||||
import PreviewHeader from './preview-header.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ContextMenuDropDown,
|
||||
ViewSwitcher
|
||||
PreviewHeader
|
||||
},
|
||||
inject: [
|
||||
'openmct',
|
||||
@ -64,12 +46,9 @@ export default {
|
||||
],
|
||||
data() {
|
||||
let domainObject = this.objectPath[0];
|
||||
let type = this.openmct.types.get(domainObject.type);
|
||||
|
||||
return {
|
||||
domainObject: domainObject,
|
||||
type: type,
|
||||
notebookEnabled: false,
|
||||
viewKey: undefined
|
||||
};
|
||||
},
|
||||
@ -97,6 +76,7 @@ export default {
|
||||
this.view.destroy();
|
||||
this.$refs.objectView.innerHTML = '';
|
||||
}
|
||||
|
||||
delete this.view;
|
||||
delete this.viewContainer;
|
||||
},
|
||||
|
@ -36,7 +36,12 @@ export default class PreviewAction {
|
||||
* Dependencies
|
||||
*/
|
||||
this._openmct = openmct;
|
||||
|
||||
if (PreviewAction.isVisible === undefined) {
|
||||
PreviewAction.isVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
invoke(objectPath) {
|
||||
let preview = new Vue({
|
||||
components: {
|
||||
@ -59,16 +64,27 @@ export default class PreviewAction {
|
||||
callback: () => overlay.dismiss()
|
||||
}
|
||||
],
|
||||
onDestroy: () => preview.$destroy()
|
||||
onDestroy: () => {
|
||||
PreviewAction.isVisible = false;
|
||||
preview.$destroy()
|
||||
}
|
||||
});
|
||||
|
||||
PreviewAction.isVisible = true;
|
||||
}
|
||||
|
||||
appliesTo(objectPath) {
|
||||
return !this._isNavigatedObject(objectPath)
|
||||
return !PreviewAction.isVisible && !this._isNavigatedObject(objectPath);
|
||||
}
|
||||
|
||||
_isNavigatedObject(objectPath) {
|
||||
let targetObject = objectPath[0];
|
||||
let navigatedObject = this._openmct.router.path[0];
|
||||
return targetObject.identifier.namespace === navigatedObject.identifier.namespace &&
|
||||
targetObject.identifier.key === navigatedObject.identifier.key;
|
||||
}
|
||||
_preventPreview(objectPath) {
|
||||
const noPreviewTypes = ['folder'];
|
||||
return noPreviewTypes.includes(objectPath[0].type);
|
||||
}
|
||||
}
|
||||
|
92
src/ui/preview/preview-header.vue
Normal file
92
src/ui/preview/preview-header.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="l-browse-bar">
|
||||
<div class="l-browse-bar__start">
|
||||
<div
|
||||
class="l-browse-bar__object-name--w"
|
||||
:class="type.cssClass"
|
||||
>
|
||||
<span class="l-browse-bar__object-name">
|
||||
{{ domainObject.name }}
|
||||
</span>
|
||||
<context-menu-drop-down :object-path="objectPath" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="l-browse-bar__end">
|
||||
<div class="l-browse-bar__actions">
|
||||
<view-switcher
|
||||
:v-if="!hideViewSwitcher"
|
||||
:views="views"
|
||||
:current-view="currentView"
|
||||
@setView="setView"
|
||||
/>
|
||||
<NotebookMenuSwitcher v-if="showNotebookMenuSwitcher"
|
||||
:domain-object="domainObject"
|
||||
:ignore-link="true"
|
||||
:object-path="objectPath"
|
||||
class="c-notebook-snapshot-menubutton"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import ContextMenuDropDown from '../../ui/components/contextMenuDropDown.vue';
|
||||
import NotebookMenuSwitcher from '@/plugins/notebook/components/notebook-menu-switcher.vue';
|
||||
import ViewSwitcher from '../../ui/layout/ViewSwitcher.vue';
|
||||
|
||||
export default {
|
||||
inject: [
|
||||
'openmct',
|
||||
'objectPath'
|
||||
],
|
||||
components: {
|
||||
ContextMenuDropDown,
|
||||
NotebookMenuSwitcher,
|
||||
ViewSwitcher
|
||||
},
|
||||
props: {
|
||||
currentView: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
domainObject: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
hideViewSwitcher: {
|
||||
type: Boolean,
|
||||
default: () => {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
showNotebookMenuSwitcher: {
|
||||
type: Boolean,
|
||||
default: () => {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
views: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: this.openmct.types.get(this.domainObject.type)
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
setView(view) {
|
||||
this.$emit('setView', view);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Reference in New Issue
Block a user