Compare commits
36 Commits
v1.1.1
...
new-eslint
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c92672feb | ||
|
|
1a508a113e | ||
|
|
2cf66986aa | ||
|
|
421c09ec2c | ||
|
|
0679b246b8 | ||
|
|
83f9c6c528 | ||
|
|
a5f3ba6259 | ||
|
|
a70facf0c8 | ||
|
|
447fe94325 | ||
|
|
8e2b666766 | ||
|
|
dcbfbdbb89 | ||
|
|
4c76bf34ab | ||
|
|
81b7a9d3e0 | ||
|
|
dc573c479c | ||
|
|
23303c910e | ||
|
|
3282934cf6 | ||
|
|
c157fab081 | ||
|
|
7c07b66cc9 | ||
|
|
7a906ccf5c | ||
|
|
ff7debfb81 | ||
|
|
92ba103f45 | ||
|
|
2c2d8d6b56 | ||
|
|
cfadb9f4fd | ||
|
|
396817b2d1 | ||
|
|
96eb6d6b74 | ||
|
|
cb5d47f66f | ||
|
|
ea90d02d66 | ||
|
|
95f73d8eb8 | ||
|
|
a37c686993 | ||
|
|
f12166097c | ||
|
|
d103a22fa0 | ||
|
|
04a60cfcbb | ||
|
|
8d723960f4 | ||
|
|
6d3cd2c699 | ||
|
|
87bf94fe0a | ||
|
|
af93823b6f |
@@ -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
|
||||
|
||||
17
.eslintrc.js
17
.eslintrc.js
@@ -66,6 +66,23 @@ module.exports = {
|
||||
],
|
||||
"dot-notation": "error",
|
||||
"indent": ["error", 4],
|
||||
|
||||
/*"array-callback-return": "error",
|
||||
"consistent-return": "error",
|
||||
"default-case-last": "error",
|
||||
"default-param-last": "error",
|
||||
"grouped-accessor-pairs": "error",
|
||||
"noalert": "error",
|
||||
"no-constructor-return": "error" */
|
||||
"no-case-declarations": "error",
|
||||
"max-classes-per-file": ["error", 1],
|
||||
"no-eq-null": "error",
|
||||
"no-eval": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
|
||||
|
||||
|
||||
"vue/html-indent": [
|
||||
"error",
|
||||
4,
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
44
index.html
44
index.html
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2017, United States Government
|
||||
Open MCT, Copyright (c) 2014-2020, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
<body>
|
||||
</body>
|
||||
<script>
|
||||
const THIRTY_SECONDS = 30 * 1000;
|
||||
const THIRTY_MINUTES = THIRTY_SECONDS * 60;
|
||||
const FIVE_MINUTES = 5 * 60 * 1000;
|
||||
const THIRTY_MINUTES = 30 * 60 * 1000;
|
||||
|
||||
[
|
||||
'example/eventGenerator'
|
||||
@@ -43,9 +43,9 @@
|
||||
openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
|
||||
);
|
||||
|
||||
openmct.install(openmct.plugins.LocalStorage());
|
||||
openmct.install(openmct.plugins.Espresso());
|
||||
openmct.install(openmct.plugins.MyItems());
|
||||
openmct.install(openmct.plugins.LocalStorage());
|
||||
openmct.install(openmct.plugins.Generator());
|
||||
openmct.install(openmct.plugins.ExampleImagery());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
@@ -63,39 +63,7 @@
|
||||
bounds: {
|
||||
start: Date.now() - THIRTY_MINUTES,
|
||||
end: Date.now()
|
||||
},
|
||||
// commonly used bounds can be stored in history
|
||||
// bounds (start and end) can accept either a milliseconds number
|
||||
// or a callback function returning a milliseconds number
|
||||
// a function is useful for invoking Date.now() at exact moment of preset selection
|
||||
presets: [
|
||||
{
|
||||
label: 'Last Day',
|
||||
bounds: {
|
||||
start: () => Date.now() - 1000 * 60 * 60 * 24,
|
||||
end: () => Date.now()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Last 2 hours',
|
||||
bounds: {
|
||||
start: () => Date.now() - 1000 * 60 * 60 * 2,
|
||||
end: () => Date.now()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Last hour',
|
||||
bounds: {
|
||||
start: () => Date.now() - 1000 * 60 * 60,
|
||||
end: () => Date.now()
|
||||
}
|
||||
}
|
||||
],
|
||||
// maximum recent bounds to retain in conductor history
|
||||
records: 10,
|
||||
// maximum duration between start and end bounds
|
||||
// for utc-based time systems this is in milliseconds
|
||||
limit: 1000 * 60 * 60 * 24
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Realtime",
|
||||
@@ -103,7 +71,7 @@
|
||||
clock: 'local',
|
||||
clockOffsets: {
|
||||
start: - THIRTY_MINUTES,
|
||||
end: THIRTY_SECONDS
|
||||
end: FIVE_MINUTES
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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: {
|
||||
|
||||
12
package.json
12
package.json
@@ -4,8 +4,7 @@
|
||||
"description": "The Open MCT core platform",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"acorn": "6.2.0",
|
||||
"angular": "1.4.14",
|
||||
"angular": "1.7.9",
|
||||
"angular-route": "1.4.14",
|
||||
"babel-eslint": "8.2.6",
|
||||
"comma-separated-values": "^3.6.4",
|
||||
@@ -43,6 +42,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",
|
||||
@@ -76,14 +76,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",
|
||||
|
||||
@@ -87,6 +87,11 @@ define([
|
||||
bootstrapper
|
||||
);
|
||||
|
||||
// Override of angular1.6 ! hashPrefix
|
||||
app.config(['$locationProvider', function ($locationProvider) {
|
||||
$locationProvider.hashPrefix('');
|
||||
}]);
|
||||
|
||||
// Apply logging levels; this must be done now, before the
|
||||
// first log statement.
|
||||
new LogLevel(logLevel).configure(app, $log);
|
||||
|
||||
@@ -71,7 +71,7 @@ define([
|
||||
},
|
||||
{
|
||||
"key": "ELASTIC_PATH",
|
||||
"value": "mct/domain_object",
|
||||
"value": "mct/_doc",
|
||||
"priority": "fallback"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -32,9 +32,9 @@ define(
|
||||
// JSLint doesn't like underscore-prefixed properties,
|
||||
// so hide them here.
|
||||
var SRC = "_source",
|
||||
REV = "_version",
|
||||
ID = "_id",
|
||||
CONFLICT = 409;
|
||||
CONFLICT = 409,
|
||||
SEQ_NO = "_seq_no",
|
||||
PRIMARY_TERM = "_primary_term";
|
||||
|
||||
/**
|
||||
* The ElasticPersistenceProvider reads and writes JSON documents
|
||||
@@ -104,7 +104,8 @@ define(
|
||||
// Get a domain object model out of ElasticSearch's response
|
||||
ElasticPersistenceProvider.prototype.getModel = function (response) {
|
||||
if (response && response[SRC]) {
|
||||
this.revs[response[ID]] = response[REV];
|
||||
this.revs[response[SEQ_NO]] = response[SEQ_NO];
|
||||
this.revs[response[PRIMARY_TERM]] = response[PRIMARY_TERM];
|
||||
return response[SRC];
|
||||
} else {
|
||||
return undefined;
|
||||
@@ -116,7 +117,8 @@ define(
|
||||
// indicate that the request failed.
|
||||
ElasticPersistenceProvider.prototype.checkResponse = function (response, key) {
|
||||
if (response && !response.error) {
|
||||
this.revs[key] = response[REV];
|
||||
this.revs[SEQ_NO] = response[SEQ_NO];
|
||||
this.revs[PRIMARY_TERM] = response[PRIMARY_TERM];
|
||||
return response;
|
||||
} else {
|
||||
return this.handleError(response, key);
|
||||
@@ -147,7 +149,7 @@ define(
|
||||
function checkUpdate(response) {
|
||||
return self.checkResponse(response, key);
|
||||
}
|
||||
return this.put(key, value, { version: this.revs[key] })
|
||||
return this.put(key, value)
|
||||
.then(checkUpdate);
|
||||
};
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ define(
|
||||
it("allows object creation", function () {
|
||||
var model = { someKey: "some value" };
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 1 }
|
||||
data: { "_id": "abc", "_seq_no": 1, "_primary_term": 1 }
|
||||
}));
|
||||
provider.createObject("testSpace", "abc", model).then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
@@ -100,7 +100,7 @@ define(
|
||||
it("allows object models to be read back", function () {
|
||||
var model = { someKey: "some value" };
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 1, "_source": model }
|
||||
data: { "_id": "abc", "_seq_no": 1, "_primary_term": 1, "_source": model }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc").then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
@@ -117,19 +117,19 @@ define(
|
||||
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
data: { "_id": "abc", "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
// Now perform an update
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 43, "_source": {} }
|
||||
data: { "_id": "abc", "_seq_no": 1, "_source": {} }
|
||||
}));
|
||||
provider.updateObject("testSpace", "abc", model).then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
url: "/test/db/abc",
|
||||
method: "PUT",
|
||||
params: { version: 42 },
|
||||
params: undefined,
|
||||
data: model
|
||||
});
|
||||
expect(capture.calls.mostRecent().args[0]).toBeTruthy();
|
||||
@@ -138,13 +138,13 @@ define(
|
||||
it("allows object deletion", function () {
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
data: { "_id": "abc", "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
// Now perform an update
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
data: { "_id": "abc", "_source": {} }
|
||||
}));
|
||||
provider.deleteObject("testSpace", "abc", {}).then(capture);
|
||||
expect(mockHttp).toHaveBeenCalledWith({
|
||||
@@ -167,13 +167,13 @@ define(
|
||||
expect(capture).toHaveBeenCalledWith(undefined);
|
||||
});
|
||||
|
||||
it("handles rejection due to version", function () {
|
||||
it("handles rejection due to _seq_no", function () {
|
||||
var model = { someKey: "some value" },
|
||||
mockErrorCallback = jasmine.createSpy('error');
|
||||
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
data: { "_id": "abc", "_seq_no": 1, "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
@@ -196,7 +196,7 @@ define(
|
||||
|
||||
// First do a read to populate rev tags...
|
||||
mockHttp.and.returnValue(mockPromise({
|
||||
data: { "_id": "abc", "_version": 42, "_source": {} }
|
||||
data: { "_id": "abc", "_seq_no": 1, "_source": {} }
|
||||
}));
|
||||
provider.readObject("testSpace", "abc");
|
||||
|
||||
|
||||
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
|
||||
@@ -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,7 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
}
|
||||
delete this.stopProvidingTelemetry;
|
||||
this.conditionSetIdentifier = undefined;
|
||||
this.isEditing = undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
>
|
||||
<div class="c-condition-h__drop-target"></div>
|
||||
<div v-if="isEditing"
|
||||
:class="{'is-current': condition.id === currentConditionId}"
|
||||
class="c-condition c-condition--edit"
|
||||
>
|
||||
<!-- Edit view -->
|
||||
@@ -167,6 +168,7 @@
|
||||
</div>
|
||||
<div v-else
|
||||
class="c-condition c-condition--browse"
|
||||
:class="{'is-current': condition.id === currentConditionId}"
|
||||
>
|
||||
<!-- Browse view -->
|
||||
<div class="c-condition__header">
|
||||
@@ -199,6 +201,10 @@ export default {
|
||||
ConditionDescription
|
||||
},
|
||||
props: {
|
||||
currentConditionId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
condition: {
|
||||
type: Object,
|
||||
required: true
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<Condition v-for="(condition, index) in conditionCollection"
|
||||
:key="condition.id"
|
||||
:condition="condition"
|
||||
:current-condition-id="currentConditionId"
|
||||
:condition-index="index"
|
||||
:telemetry="telemetryObjs"
|
||||
:is-editing="isEditing"
|
||||
@@ -107,7 +108,8 @@ export default {
|
||||
moveIndex: undefined,
|
||||
isDragging: false,
|
||||
defaultOutput: undefined,
|
||||
dragCounter: 0
|
||||
dragCounter: 0,
|
||||
currentConditionId: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -145,6 +147,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleConditionSetResultUpdated(data) {
|
||||
this.currentConditionId = data.conditionId;
|
||||
this.$emit('conditionSetResultUpdated', data)
|
||||
},
|
||||
observeForChanges() {
|
||||
|
||||
@@ -190,6 +190,7 @@
|
||||
}
|
||||
|
||||
.c-condition {
|
||||
border: 1px solid transparent;
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
|
||||
@@ -234,6 +235,12 @@
|
||||
&__summary {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
&.is-current {
|
||||
$c: $colorBodyFg;
|
||||
border-color: rgba($c, 0.2);
|
||||
background: rgba($c, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** CONDITION DEFINITION, EDITING */
|
||||
|
||||
@@ -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.2);
|
||||
background: rgba($c, 0.2);
|
||||
}
|
||||
|
||||
.is-editing & {
|
||||
cursor: pointer;
|
||||
pointer-events: initial;
|
||||
transition: $transOut;
|
||||
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, 0.1);
|
||||
transition: $transIn;
|
||||
}
|
||||
|
||||
&.is-current {
|
||||
$c: $editUIColorBg;
|
||||
border-color: $c;
|
||||
background: rgba($c, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-style {
|
||||
|
||||
@@ -34,6 +34,10 @@ const convertToStrings = (input) => {
|
||||
return stringInputs;
|
||||
};
|
||||
|
||||
const joinValues = (values, length) => {
|
||||
return values.slice(0, length).join(', ');
|
||||
};
|
||||
|
||||
export const OPERATIONS = [
|
||||
{
|
||||
name: 'equalTo',
|
||||
@@ -44,7 +48,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is ' + values.join(', ');
|
||||
return ' is ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -56,7 +60,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is not ' + values.join(', ');
|
||||
return ' is not ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -68,7 +72,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' > ' + values.join(', ');
|
||||
return ' > ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -80,7 +84,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' < ' + values.join(', ');
|
||||
return ' < ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -92,7 +96,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' >= ' + values.join(', ');
|
||||
return ' >= ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -104,7 +108,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' <= ' + values.join(', ');
|
||||
return ' <= ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -146,7 +150,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' contains ' + values.join(', ');
|
||||
return ' contains ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -158,7 +162,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' does not contain ' + values.join(', ');
|
||||
return ' does not contain ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -170,7 +174,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' starts with ' + values.join(', ');
|
||||
return ' starts with ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -182,7 +186,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' ends with ' + values.join(', ');
|
||||
return ' ends with ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -194,7 +198,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is exactly ' + values.join(', ');
|
||||
return ' is exactly ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -231,7 +235,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['enum'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is ' + values.join(', ');
|
||||
return ' is ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -244,7 +248,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['enum'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is not ' + values.join(', ');
|
||||
return ' is not ' + joinValues(values, 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ define([], function () {
|
||||
this.timeFormat = 'local-format';
|
||||
this.durationFormat = 'duration';
|
||||
|
||||
this.isUTCBased = true;
|
||||
this.isUTCBased = false;
|
||||
}
|
||||
|
||||
return LocalTimeSystem;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<script>
|
||||
import Snapshot from '../snapshot';
|
||||
import { clearDefaultNotebook, getDefaultNotebook } from '../utils/notebook-storage';
|
||||
import { getDefaultNotebook } from '../utils/notebook-storage';
|
||||
import { NOTEBOOK_DEFAULT, NOTEBOOK_SNAPSHOT } from '../notebook-constants';
|
||||
|
||||
export default {
|
||||
@@ -40,6 +40,18 @@ export default {
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
ignoreLink: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
objectPath: {
|
||||
type: Array,
|
||||
default() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -60,28 +72,22 @@ export default {
|
||||
methods: {
|
||||
async setNotebookTypes() {
|
||||
const notebookTypes = [];
|
||||
let defaultPath = '';
|
||||
const defaultNotebook = getDefaultNotebook();
|
||||
|
||||
if (defaultNotebook) {
|
||||
const domainObject = await this.openmct.objects.get(defaultNotebook.notebookMeta.identifier)
|
||||
.then(d => d);
|
||||
const domainObject = defaultNotebook.domainObject;
|
||||
|
||||
if (!domainObject.location) {
|
||||
clearDefaultNotebook();
|
||||
} else {
|
||||
defaultPath = `${domainObject.name} - ${defaultNotebook.section.name} - ${defaultNotebook.page.name}`;
|
||||
if (domainObject.location) {
|
||||
const defaultPath = `${domainObject.name} - ${defaultNotebook.section.name} - ${defaultNotebook.page.name}`;
|
||||
|
||||
notebookTypes.push({
|
||||
cssClass: 'icon-notebook',
|
||||
name: `Save to Notebook ${defaultPath}`,
|
||||
type: NOTEBOOK_DEFAULT
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultPath.length !== 0) {
|
||||
notebookTypes.push({
|
||||
cssClass: 'icon-notebook',
|
||||
name: `Save to Notebook ${defaultPath}`,
|
||||
type: NOTEBOOK_DEFAULT
|
||||
});
|
||||
}
|
||||
|
||||
notebookTypes.push({
|
||||
cssClass: 'icon-notebook',
|
||||
name: 'Save to Notebook Snapshots',
|
||||
@@ -97,17 +103,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,6 +239,7 @@ export default {
|
||||
const section = this.getSelectedSection();
|
||||
|
||||
return {
|
||||
domainObject: this.internalDomainObject,
|
||||
notebookMeta,
|
||||
section,
|
||||
page
|
||||
@@ -440,7 +441,7 @@ export default {
|
||||
async updateDefaultNotebook(notebookStorage) {
|
||||
const defaultNotebookObject = await this.getDefaultNotebookObject();
|
||||
this.removeDefaultClass(defaultNotebookObject);
|
||||
setDefaultNotebook(notebookStorage);
|
||||
setDefaultNotebook(this.openmct, notebookStorage);
|
||||
this.addDefaultClass();
|
||||
this.defaultSectionId = notebookStorage.section.id;
|
||||
this.defaultPageId = notebookStorage.page.id;
|
||||
@@ -495,7 +496,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (section.id !== defaultNotebookSection.id) {
|
||||
if (id !== defaultNotebookSection.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,46 @@
|
||||
const NOTEBOOK_LOCAL_STORAGE = 'notebook-storage';
|
||||
let currentNotebookObject = null;
|
||||
let unlisten = null;
|
||||
|
||||
function defaultNotebookObjectChanged(newDomainObject) {
|
||||
if (newDomainObject.location !== null) {
|
||||
currentNotebookObject = newDomainObject;
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
notebookStorage.domainObject = newDomainObject;
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
unlisten = null;
|
||||
}
|
||||
|
||||
clearDefaultNotebook();
|
||||
}
|
||||
|
||||
function observeDefaultNotebookObject(openmct, notebookStorage) {
|
||||
const domainObject = notebookStorage.domainObject;
|
||||
if (currentNotebookObject
|
||||
&& currentNotebookObject.identifier.key === domainObject.identifier.key) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
unlisten = null;
|
||||
}
|
||||
|
||||
unlisten = openmct.objects.observe(notebookStorage.domainObject, '*', defaultNotebookObjectChanged);
|
||||
}
|
||||
|
||||
function saveDefaultNotebook(notebookStorage) {
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
}
|
||||
|
||||
export function clearDefaultNotebook() {
|
||||
currentNotebookObject = null;
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, null);
|
||||
}
|
||||
|
||||
@@ -10,20 +50,21 @@ export function getDefaultNotebook() {
|
||||
return JSON.parse(notebookStorage);
|
||||
}
|
||||
|
||||
export function setDefaultNotebook(notebookStorage) {
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
export function setDefaultNotebook(openmct, notebookStorage) {
|
||||
observeDefaultNotebookObject(openmct, notebookStorage);
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
}
|
||||
|
||||
export function setDefaultNotebookSection(section) {
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
|
||||
notebookStorage.section = section;
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
|
||||
}
|
||||
|
||||
export function setDefaultNotebookPage(page) {
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
notebookStorage.page = page;
|
||||
window.localStorage.setItem(NOTEBOOK_LOCAL_STORAGE, JSON.stringify(notebookStorage));
|
||||
saveDefaultNotebook(notebookStorage);
|
||||
}
|
||||
|
||||
@@ -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()"
|
||||
|
||||
@@ -54,27 +54,29 @@ function (
|
||||
* @constructor
|
||||
*/
|
||||
function MCTChartController($scope) {
|
||||
this.$scope = $scope;
|
||||
this.isDestroyed = false;
|
||||
this.lines = [];
|
||||
this.pointSets = [];
|
||||
this.alarmSets = [];
|
||||
this.offset = {};
|
||||
this.config = $scope.config;
|
||||
this.listenTo(this.$scope, '$destroy', this.destroy, this);
|
||||
this.draw = this.draw.bind(this);
|
||||
this.scheduleDraw = this.scheduleDraw.bind(this);
|
||||
this.seriesElements = new WeakMap();
|
||||
this.$onInit = () => {
|
||||
this.$scope = $scope;
|
||||
this.isDestroyed = false;
|
||||
this.lines = [];
|
||||
this.pointSets = [];
|
||||
this.alarmSets = [];
|
||||
this.offset = {};
|
||||
this.config = $scope.config;
|
||||
this.listenTo(this.$scope, '$destroy', this.destroy, this);
|
||||
this.draw = this.draw.bind(this);
|
||||
this.scheduleDraw = this.scheduleDraw.bind(this);
|
||||
this.seriesElements = new WeakMap();
|
||||
|
||||
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.xAxis, 'change:key', this.clearOffset, this);
|
||||
this.listenTo(this.config.yAxis, 'change', this.scheduleDraw);
|
||||
this.listenTo(this.config.xAxis, 'change', this.scheduleDraw);
|
||||
this.$scope.$watch('highlights', this.scheduleDraw);
|
||||
this.$scope.$watch('rectangles', this.scheduleDraw);
|
||||
this.config.series.forEach(this.onSeriesAdd, this);
|
||||
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.xAxis, 'change:key', this.clearOffset, this);
|
||||
this.listenTo(this.config.yAxis, 'change', this.scheduleDraw);
|
||||
this.listenTo(this.config.xAxis, 'change', this.scheduleDraw);
|
||||
this.$scope.$watch('highlights', this.scheduleDraw);
|
||||
this.$scope.$watch('rectangles', this.scheduleDraw);
|
||||
this.config.series.forEach(this.onSeriesAdd, this);
|
||||
}
|
||||
}
|
||||
|
||||
eventHelpers.extend(MCTChartController.prototype);
|
||||
|
||||
@@ -322,15 +322,7 @@ define([
|
||||
* a point to the end without dupe checking.
|
||||
*/
|
||||
add: function (point, appendOnly) {
|
||||
var insertIndex = this.data.length,
|
||||
currentYVal = this.getYVal(point),
|
||||
lastYVal = this.getYVal(this.data[insertIndex - 1]);
|
||||
|
||||
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
|
||||
console.warn('[Plot] Invalid Y Values detected');
|
||||
return;
|
||||
}
|
||||
|
||||
var insertIndex = this.data.length;
|
||||
if (!appendOnly) {
|
||||
insertIndex = this.sortedIndex(point);
|
||||
if (this.getXVal(this.data[insertIndex]) === this.getXVal(point)) {
|
||||
@@ -340,21 +332,11 @@ define([
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.updateStats(point);
|
||||
point.mctLimitState = this.evaluate(point);
|
||||
this.data.splice(insertIndex, 0, point);
|
||||
this.emit('add', point, insertIndex, this);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
isValueInvalid: function (val) {
|
||||
return Number.isNaN(val) || val === undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a point from the data array and notify listeners.
|
||||
* @private
|
||||
|
||||
@@ -182,23 +182,6 @@ define([
|
||||
this.set('format', yFormat.format.bind(yFormat));
|
||||
this.set('values', yMetadata.values);
|
||||
if (!label) {
|
||||
var labelName = series.map(function (s) {
|
||||
return s.metadata.value(s.get('yKey')).name;
|
||||
}).reduce(function (a, b) {
|
||||
if (a === undefined) {
|
||||
return b;
|
||||
}
|
||||
if (a === b) {
|
||||
return a;
|
||||
}
|
||||
return '';
|
||||
}, undefined);
|
||||
|
||||
if (labelName) {
|
||||
this.set('label', labelName);
|
||||
return;
|
||||
}
|
||||
|
||||
var labelUnits = series.map(function (s) {
|
||||
return s.metadata.value(s.get('yKey')).units;
|
||||
}).reduce(function (a, b) {
|
||||
@@ -210,11 +193,22 @@ define([
|
||||
}
|
||||
return '';
|
||||
}, undefined);
|
||||
|
||||
if (labelUnits) {
|
||||
this.set('label', labelUnits);
|
||||
return;
|
||||
}
|
||||
var labelName = series.map(function (s) {
|
||||
return s.metadata.value(s.get('yKey')).name;
|
||||
}).reduce(function (a, b) {
|
||||
if (a === undefined) {
|
||||
return b;
|
||||
}
|
||||
if (a === b) {
|
||||
return a;
|
||||
}
|
||||
return '';
|
||||
}, undefined);
|
||||
this.set('label', labelName);
|
||||
}
|
||||
},
|
||||
defaults: function (options) {
|
||||
|
||||
@@ -34,25 +34,27 @@ define([
|
||||
* values near the cursor.
|
||||
*/
|
||||
function MCTPlotController($scope, $element, $window) {
|
||||
this.$scope = $scope;
|
||||
this.$scope.config = this.config;
|
||||
this.$scope.plot = this;
|
||||
this.$element = $element;
|
||||
this.$window = $window;
|
||||
this.$onInit = () => {
|
||||
this.$scope = $scope;
|
||||
this.$scope.config = this.config;
|
||||
this.$scope.plot = this;
|
||||
this.$element = $element;
|
||||
this.$window = $window;
|
||||
|
||||
this.xScale = new LinearScale(this.config.xAxis.get('displayRange'));
|
||||
this.yScale = new LinearScale(this.config.yAxis.get('displayRange'));
|
||||
this.xScale = new LinearScale(this.config.xAxis.get('displayRange'));
|
||||
this.yScale = new LinearScale(this.config.yAxis.get('displayRange'));
|
||||
|
||||
this.pan = undefined;
|
||||
this.marquee = undefined;
|
||||
this.pan = undefined;
|
||||
this.marquee = undefined;
|
||||
|
||||
this.chartElementBounds = undefined;
|
||||
this.tickUpdate = false;
|
||||
this.chartElementBounds = undefined;
|
||||
this.tickUpdate = false;
|
||||
|
||||
this.$scope.plotHistory = this.plotHistory = [];
|
||||
this.listenTo(this.$scope, 'plot:clearHistory', this.clear, this);
|
||||
this.$scope.plotHistory = this.plotHistory = [];
|
||||
this.listenTo(this.$scope, 'plot:clearHistory', this.clear, this);
|
||||
|
||||
this.initialize();
|
||||
this.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
MCTPlotController.$inject = ['$scope', '$element', '$window'];
|
||||
@@ -323,7 +325,7 @@ define([
|
||||
} else {
|
||||
// A history entry is created by startMarquee, need to remove
|
||||
// if marquee zoom doesn't occur.
|
||||
this.plotHistory.pop();
|
||||
this.back();
|
||||
}
|
||||
this.$scope.rectangles = [];
|
||||
this.marquee = undefined;
|
||||
|
||||
@@ -114,15 +114,17 @@ define([
|
||||
}
|
||||
|
||||
function MCTTicksController($scope, $element) {
|
||||
this.$scope = $scope;
|
||||
this.$element = $element;
|
||||
this.$onInit = () => {
|
||||
this.$scope = $scope;
|
||||
this.$element = $element;
|
||||
|
||||
this.tickCount = 4;
|
||||
this.tickUpdate = false;
|
||||
this.listenTo(this.axis, 'change:displayRange', this.updateTicks, this);
|
||||
this.listenTo(this.axis, 'change:format', this.updateTicks, this);
|
||||
this.listenTo(this.$scope, '$destroy', this.stopListening, this);
|
||||
this.updateTicks();
|
||||
this.tickCount = 4;
|
||||
this.tickUpdate = false;
|
||||
this.listenTo(this.axis, 'change:displayRange', this.updateTicks, this);
|
||||
this.listenTo(this.axis, 'change:format', this.updateTicks, this);
|
||||
this.listenTo(this.$scope, '$destroy', this.stopListening, this);
|
||||
this.updateTicks();
|
||||
}
|
||||
}
|
||||
|
||||
MCTTicksController.$inject = ['$scope', '$element'];
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -227,8 +227,9 @@ define([
|
||||
};
|
||||
|
||||
PlotController.prototype.stopLoading = function () {
|
||||
this.$scope.pending -= 1;
|
||||
this.$scope.$digest();
|
||||
this.$scope.$evalAsync(() => {
|
||||
this.$scope.pending -= 1;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -88,7 +88,8 @@ define([
|
||||
var bundleMap = {
|
||||
LocalStorage: 'platform/persistence/local',
|
||||
MyItems: 'platform/features/my-items',
|
||||
CouchDB: 'platform/persistence/couch'
|
||||
CouchDB: 'platform/persistence/couch',
|
||||
Elasticsearch: 'platform/persistence/elastic'
|
||||
};
|
||||
|
||||
var plugins = _.mapValues(bundleMap, function (bundleName, pluginName) {
|
||||
|
||||
@@ -46,23 +46,11 @@ define(
|
||||
filter = filter.trim().toLowerCase();
|
||||
|
||||
let rowsToFilter = this.getRowsToFilter(columnKey, filter);
|
||||
|
||||
if (filter.length === 0) {
|
||||
delete this.columnFilters[columnKey];
|
||||
} else {
|
||||
this.columnFilters[columnKey] = filter;
|
||||
}
|
||||
|
||||
this.rows = rowsToFilter.filter(this.matchesFilters, this);
|
||||
this.emit('filter');
|
||||
}
|
||||
|
||||
setColumnRegexFilter(columnKey, filter) {
|
||||
filter = filter.trim();
|
||||
|
||||
let rowsToFilter = this.masterCollection.getRows();
|
||||
|
||||
this.columnFilters[columnKey] = new RegExp(filter);
|
||||
this.rows = rowsToFilter.filter(this.matchesFilters, this);
|
||||
this.emit('filter');
|
||||
}
|
||||
@@ -82,10 +70,6 @@ define(
|
||||
* @private
|
||||
*/
|
||||
isSubsetOfCurrentFilter(columnKey, filter) {
|
||||
if (this.columnFilters[columnKey] instanceof RegExp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.columnFilters[columnKey] &&
|
||||
filter.startsWith(this.columnFilters[columnKey]) &&
|
||||
// startsWith check will otherwise fail when filter cleared
|
||||
@@ -112,11 +96,7 @@ define(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.columnFilters[key] instanceof RegExp) {
|
||||
doesMatchFilters = this.columnFilters[key].test(formattedValue);
|
||||
} else {
|
||||
doesMatchFilters = formattedValue.toLowerCase().indexOf(this.columnFilters[key]) !== -1;
|
||||
}
|
||||
doesMatchFilters = formattedValue.toLowerCase().indexOf(this.columnFilters[key]) !== -1;
|
||||
});
|
||||
return doesMatchFilters;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,17 +186,7 @@
|
||||
class="c-table__search"
|
||||
@input="filterChanged(key)"
|
||||
@clear="clearFilter(key)"
|
||||
>
|
||||
|
||||
<button
|
||||
class="c-search__use-regex"
|
||||
:class="{ 'is-active': enableRegexSearch[key] }"
|
||||
title="Click to enable regex: enter a string with slashes, like this: /regex_exp/"
|
||||
@click="toggleRegex(key)"
|
||||
>
|
||||
/R/
|
||||
</button>
|
||||
</search>
|
||||
/>
|
||||
</table-column-header>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -346,8 +336,7 @@ export default {
|
||||
markCounter: 0,
|
||||
paused: false,
|
||||
markedRows: [],
|
||||
isShowingMarkedRowsOnly: false,
|
||||
enableRegexSearch: {}
|
||||
isShowingMarkedRowsOnly: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -554,16 +543,7 @@ export default {
|
||||
this.headersHolderEl.scrollLeft = this.scrollable.scrollLeft;
|
||||
},
|
||||
filterChanged(columnKey) {
|
||||
if (this.enableRegexSearch[columnKey]) {
|
||||
if (this.isCompleteRegex(this.filters[columnKey])) {
|
||||
this.table.filteredRows.setColumnRegexFilter(columnKey, this.filters[columnKey].slice(1,-1));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.table.filteredRows.setColumnFilter(columnKey, this.filters[columnKey]);
|
||||
}
|
||||
|
||||
this.table.filteredRows.setColumnFilter(columnKey, this.filters[columnKey]);
|
||||
this.setHeight();
|
||||
},
|
||||
clearFilter(columnKey) {
|
||||
@@ -889,18 +869,6 @@ export default {
|
||||
this.isAutosizeEnabled = true;
|
||||
|
||||
this.$nextTick().then(this.calculateColumnWidths);
|
||||
},
|
||||
toggleRegex(key) {
|
||||
this.$set(this.filters, key, '');
|
||||
|
||||
if (this.enableRegexSearch[key] === undefined) {
|
||||
this.$set(this.enableRegexSearch, key, true)
|
||||
} else {
|
||||
this.$set(this.enableRegexSearch, key, !this.enableRegexSearch[key]);
|
||||
}
|
||||
},
|
||||
isCompleteRegex(string) {
|
||||
return (string.length > 2 && string[0] === '/' && string[string.length - 1] === '/')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="c-conductor"
|
||||
:class="[
|
||||
{ 'is-zooming': isZooming },
|
||||
{ 'is-panning': isPanning },
|
||||
{ 'alt-pressed': altPressed },
|
||||
isFixed ? 'is-fixed-mode' : 'is-realtime-mode'
|
||||
]"
|
||||
:class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']"
|
||||
>
|
||||
<form
|
||||
ref="conductorForm"
|
||||
@@ -57,7 +52,7 @@
|
||||
type="text"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
@change="validateAllBounds('startDate'); submitForm()"
|
||||
@change="validateAllBounds(); submitForm()"
|
||||
>
|
||||
<date-picker
|
||||
v-if="isFixed && isUTCBased"
|
||||
@@ -97,7 +92,7 @@
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
:disabled="!isFixed"
|
||||
@change="validateAllBounds('endDate'); submitForm()"
|
||||
@change="validateAllBounds(); submitForm()"
|
||||
>
|
||||
<date-picker
|
||||
v-if="isFixed && isUTCBased"
|
||||
@@ -127,25 +122,14 @@
|
||||
|
||||
<conductor-axis
|
||||
class="c-conductor__ticks"
|
||||
:view-bounds="viewBounds"
|
||||
:is-fixed="isFixed"
|
||||
:alt-pressed="altPressed"
|
||||
@endPan="endPan"
|
||||
@endZoom="endZoom"
|
||||
@panAxis="pan"
|
||||
@zoomAxis="zoom"
|
||||
:bounds="rawBounds"
|
||||
@panAxis="setViewFromBounds"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div class="c-conductor__controls">
|
||||
<!-- Mode, time system menu buttons and duration slider -->
|
||||
<ConductorMode class="c-conductor__mode-select" />
|
||||
<ConductorTimeSystem class="c-conductor__time-system-select" />
|
||||
<ConductorHistory
|
||||
v-if="isFixed"
|
||||
class="c-conductor__history-select"
|
||||
:bounds="openmct.time.bounds()"
|
||||
:time-system="timeSystem"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
type="submit"
|
||||
@@ -161,7 +145,6 @@ import ConductorTimeSystem from './ConductorTimeSystem.vue';
|
||||
import DatePicker from './DatePicker.vue';
|
||||
import ConductorAxis from './ConductorAxis.vue';
|
||||
import ConductorModeIcon from './ConductorModeIcon.vue';
|
||||
import ConductorHistory from './ConductorHistory.vue'
|
||||
|
||||
const DEFAULT_DURATION_FORMATTER = 'duration';
|
||||
|
||||
@@ -172,8 +155,7 @@ export default {
|
||||
ConductorTimeSystem,
|
||||
DatePicker,
|
||||
ConductorAxis,
|
||||
ConductorModeIcon,
|
||||
ConductorHistory
|
||||
ConductorModeIcon
|
||||
},
|
||||
data() {
|
||||
let bounds = this.openmct.time.bounds();
|
||||
@@ -183,7 +165,6 @@ export default {
|
||||
let durationFormatter = this.getFormatter(timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
|
||||
|
||||
return {
|
||||
timeSystem: timeSystem,
|
||||
timeFormatter: timeFormatter,
|
||||
durationFormatter: durationFormatter,
|
||||
offsets: {
|
||||
@@ -194,68 +175,29 @@ export default {
|
||||
start: timeFormatter.format(bounds.start),
|
||||
end: timeFormatter.format(bounds.end)
|
||||
},
|
||||
viewBounds: {
|
||||
rawBounds: {
|
||||
start: bounds.start,
|
||||
end: bounds.end
|
||||
},
|
||||
isFixed: this.openmct.time.clock() === undefined,
|
||||
isUTCBased: timeSystem.isUTCBased,
|
||||
showDatePicker: false,
|
||||
altPressed: false,
|
||||
isPanning: false,
|
||||
isZooming: false
|
||||
showDatePicker: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('keydown', this.handleKeyDown);
|
||||
document.addEventListener('keyup', this.handleKeyUp);
|
||||
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));
|
||||
|
||||
this.openmct.time.on('bounds', this.setViewFromBounds);
|
||||
this.openmct.time.on('timeSystem', this.setTimeSystem);
|
||||
this.openmct.time.on('clock', this.setViewFromClock);
|
||||
this.openmct.time.on('clockOffsets', this.setViewFromOffsets)
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.removeEventListener('keydown', this.handleKeyDown);
|
||||
document.removeEventListener('keyup', this.handleKeyUp);
|
||||
},
|
||||
methods: {
|
||||
handleKeyDown(event) {
|
||||
if (event.key === 'Alt') {
|
||||
this.altPressed = true;
|
||||
}
|
||||
},
|
||||
handleKeyUp(event) {
|
||||
if (event.key === 'Alt') {
|
||||
this.altPressed = false;
|
||||
}
|
||||
},
|
||||
pan(bounds) {
|
||||
this.isPanning = true;
|
||||
this.setViewFromBounds(bounds);
|
||||
},
|
||||
endPan(bounds) {
|
||||
this.isPanning = false;
|
||||
if (bounds) {
|
||||
this.openmct.time.bounds(bounds);
|
||||
}
|
||||
},
|
||||
zoom(bounds) {
|
||||
this.isZooming = true;
|
||||
this.formattedBounds.start = this.timeFormatter.format(bounds.start);
|
||||
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
|
||||
},
|
||||
endZoom(bounds) {
|
||||
const _bounds = bounds ? bounds : this.openmct.time.bounds();
|
||||
this.isZooming = false;
|
||||
|
||||
this.openmct.time.bounds(_bounds);
|
||||
},
|
||||
setTimeSystem(timeSystem) {
|
||||
this.timeSystem = timeSystem
|
||||
this.timeFormatter = this.getFormatter(timeSystem.timeFormat);
|
||||
this.durationFormatter = this.getFormatter(
|
||||
timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
|
||||
|
||||
this.isUTCBased = timeSystem.isUTCBased;
|
||||
},
|
||||
setOffsetsFromView($event) {
|
||||
@@ -295,8 +237,8 @@ export default {
|
||||
setViewFromBounds(bounds) {
|
||||
this.formattedBounds.start = this.timeFormatter.format(bounds.start);
|
||||
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
|
||||
this.viewBounds.start = bounds.start;
|
||||
this.viewBounds.end = bounds.end;
|
||||
this.rawBounds.start = bounds.start;
|
||||
this.rawBounds.end = bounds.end;
|
||||
},
|
||||
setViewFromOffsets(offsets) {
|
||||
this.offsets.start = this.durationFormatter.format(Math.abs(offsets.start));
|
||||
@@ -309,15 +251,6 @@ export default {
|
||||
this.setOffsetsFromView();
|
||||
}
|
||||
},
|
||||
getBoundsLimit() {
|
||||
const configuration = this.configuration.menuOptions
|
||||
.filter(option => option.timeSystem === this.timeSystem.key)
|
||||
.find(option => option.limit);
|
||||
|
||||
const limit = configuration ? configuration.limit : undefined;
|
||||
|
||||
return limit;
|
||||
},
|
||||
clearAllValidation() {
|
||||
if (this.isFixed) {
|
||||
[this.$refs.startDate, this.$refs.endDate].forEach(this.clearValidationForInput);
|
||||
@@ -329,52 +262,36 @@ export default {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
},
|
||||
validateAllBounds(ref) {
|
||||
if (!this.areBoundsFormatsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let validationResult = true;
|
||||
const currentInput = this.$refs[ref];
|
||||
|
||||
validateAllBounds() {
|
||||
return [this.$refs.startDate, this.$refs.endDate].every((input) => {
|
||||
let boundsValues = {
|
||||
start: this.timeFormatter.parse(this.formattedBounds.start),
|
||||
end: this.timeFormatter.parse(this.formattedBounds.end)
|
||||
};
|
||||
const limit = this.getBoundsLimit();
|
||||
let validationResult = true;
|
||||
let formattedDate;
|
||||
|
||||
if (
|
||||
this.timeSystem.isUTCBased
|
||||
&& limit
|
||||
&& boundsValues.end - boundsValues.start > limit
|
||||
) {
|
||||
if (input === currentInput) {
|
||||
validationResult = "Start and end difference exceeds allowable limit";
|
||||
}
|
||||
if (input === this.$refs.startDate) {
|
||||
formattedDate = this.formattedBounds.start;
|
||||
} else {
|
||||
if (input === currentInput) {
|
||||
validationResult = this.openmct.time.validateBounds(boundsValues);
|
||||
}
|
||||
formattedDate = this.formattedBounds.end;
|
||||
}
|
||||
|
||||
return this.handleValidationResults(input, validationResult);
|
||||
});
|
||||
},
|
||||
areBoundsFormatsValid() {
|
||||
let validationResult = true;
|
||||
|
||||
return [this.$refs.startDate, this.$refs.endDate].every((input) => {
|
||||
const formattedDate = input === this.$refs.startDate
|
||||
? this.formattedBounds.start
|
||||
: this.formattedBounds.end
|
||||
;
|
||||
|
||||
if (!this.timeFormatter.validate(formattedDate)) {
|
||||
validationResult = 'Invalid date';
|
||||
} else {
|
||||
let boundsValues = {
|
||||
start: this.timeFormatter.parse(this.formattedBounds.start),
|
||||
end: this.timeFormatter.parse(this.formattedBounds.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateBounds(boundsValues);
|
||||
}
|
||||
|
||||
return this.handleValidationResults(input, validationResult);
|
||||
if (validationResult !== true) {
|
||||
input.setCustomValidity(validationResult);
|
||||
input.title = validationResult;
|
||||
return false;
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
validateAllOffsets(event) {
|
||||
@@ -398,20 +315,17 @@ export default {
|
||||
validationResult = this.openmct.time.validateOffsets(offsetValues);
|
||||
}
|
||||
|
||||
return this.handleValidationResults(input, validationResult);
|
||||
if (validationResult !== true) {
|
||||
input.setCustomValidity(validationResult);
|
||||
input.title = validationResult;
|
||||
return false;
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
handleValidationResults(input, validationResult) {
|
||||
if (validationResult !== true) {
|
||||
input.setCustomValidity(validationResult);
|
||||
input.title = validationResult;
|
||||
return false;
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
return true;
|
||||
}
|
||||
},
|
||||
submitForm() {
|
||||
// Allow Vue model to catch up to user input.
|
||||
// Submitting form will cause validation messages to display (but only if triggered by button click)
|
||||
@@ -424,12 +338,12 @@ export default {
|
||||
},
|
||||
startDateSelected(date) {
|
||||
this.formattedBounds.start = this.timeFormatter.format(date);
|
||||
this.validateAllBounds('startDate');
|
||||
this.validateAllBounds();
|
||||
this.submitForm();
|
||||
},
|
||||
endDateSelected(date) {
|
||||
this.formattedBounds.end = this.timeFormatter.format(date);
|
||||
this.validateAllBounds('endDate');
|
||||
this.validateAllBounds();
|
||||
this.submitForm();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,7 @@
|
||||
ref="axisHolder"
|
||||
class="c-conductor-axis"
|
||||
@mousedown="dragStart($event)"
|
||||
>
|
||||
<div
|
||||
class="c-conductor-axis__zoom-indicator"
|
||||
:style="zoomStyle"
|
||||
></div>
|
||||
</div>
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -48,81 +43,52 @@ const PIXELS_PER_TICK_WIDE = 200;
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
viewBounds: {
|
||||
bounds: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
isFixed: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
altPressed: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inPanMode: false,
|
||||
dragStartX: undefined,
|
||||
dragX: undefined,
|
||||
zoomStyle: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
inZoomMode() {
|
||||
return !this.inPanMode;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
viewBounds: {
|
||||
handler() {
|
||||
bounds: {
|
||||
handler(bounds) {
|
||||
this.setScale();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let vis = d3Selection.select(this.$refs.axisHolder).append("svg:svg");
|
||||
let axisHolder = this.$refs.axisHolder;
|
||||
let height = axisHolder.offsetHeight;
|
||||
let vis = d3Selection.select(axisHolder)
|
||||
.append("svg:svg")
|
||||
.attr("width", "100%")
|
||||
.attr("height", height);
|
||||
|
||||
this.width = this.$refs.axisHolder.clientWidth;
|
||||
this.xAxis = d3Axis.axisTop();
|
||||
this.dragging = false;
|
||||
|
||||
// draw x axis with labels. CSS is used to position them.
|
||||
this.axisElement = vis.append("g")
|
||||
.attr("class", "axis");
|
||||
this.axisElement = vis.append("g");
|
||||
|
||||
this.setViewFromTimeSystem(this.openmct.time.timeSystem());
|
||||
this.setAxisDimensions();
|
||||
this.setScale();
|
||||
|
||||
//Respond to changes in conductor
|
||||
this.openmct.time.on("timeSystem", this.setViewFromTimeSystem);
|
||||
setInterval(this.resize, RESIZE_POLL_INTERVAL);
|
||||
},
|
||||
destroyed() {
|
||||
},
|
||||
methods: {
|
||||
setAxisDimensions() {
|
||||
const axisHolder = this.$refs.axisHolder;
|
||||
const rect = axisHolder.getBoundingClientRect();
|
||||
|
||||
this.left = Math.round(rect.left);
|
||||
this.width = axisHolder.clientWidth;
|
||||
},
|
||||
setScale() {
|
||||
if (!this.width) {
|
||||
return;
|
||||
}
|
||||
|
||||
let timeSystem = this.openmct.time.timeSystem();
|
||||
let bounds = this.bounds;
|
||||
|
||||
if (timeSystem.isUTCBased) {
|
||||
this.xScale.domain(
|
||||
[new Date(this.viewBounds.start), new Date(this.viewBounds.end)]
|
||||
);
|
||||
this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]);
|
||||
} else {
|
||||
this.xScale.domain(
|
||||
[this.viewBounds.start, this.viewBounds.end]
|
||||
);
|
||||
this.xScale.domain([bounds.start, bounds.end]);
|
||||
}
|
||||
|
||||
this.xAxis.scale(this.xScale);
|
||||
@@ -136,7 +102,7 @@ export default {
|
||||
this.xAxis.ticks(this.width / PIXELS_PER_TICK);
|
||||
}
|
||||
|
||||
this.msPerPixel = (this.viewBounds.end - this.viewBounds.start) / this.width;
|
||||
this.msPerPixel = (bounds.end - bounds.start) / this.width;
|
||||
},
|
||||
setViewFromTimeSystem(timeSystem) {
|
||||
//The D3 scale used depends on the type of time system as d3
|
||||
@@ -154,8 +120,9 @@ export default {
|
||||
},
|
||||
getActiveFormatter() {
|
||||
let timeSystem = this.openmct.time.timeSystem();
|
||||
let isFixed = this.openmct.time.clock() === undefined;
|
||||
|
||||
if (this.isFixed) {
|
||||
if (isFixed) {
|
||||
return this.getFormatter(timeSystem.timeFormat);
|
||||
} else {
|
||||
return this.getFormatter(timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
|
||||
@@ -167,131 +134,45 @@ export default {
|
||||
}).formatter;
|
||||
},
|
||||
dragStart($event) {
|
||||
if (this.isFixed) {
|
||||
let isFixed = this.openmct.time.clock() === undefined;
|
||||
if (isFixed) {
|
||||
this.dragStartX = $event.clientX;
|
||||
|
||||
if (this.altPressed) {
|
||||
this.inPanMode = true;
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', this.drag);
|
||||
document.addEventListener('mouseup', this.dragEnd, {
|
||||
once: true
|
||||
});
|
||||
|
||||
if (this.inZoomMode) {
|
||||
this.startZoom();
|
||||
}
|
||||
}
|
||||
},
|
||||
drag($event) {
|
||||
if (!this.dragging) {
|
||||
this.dragging = true;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
this.dragX = $event.clientX;
|
||||
this.inPanMode ? this.pan() : this.zoom();
|
||||
requestAnimationFrame(()=>{
|
||||
let deltaX = $event.clientX - this.dragStartX;
|
||||
let percX = deltaX / this.width;
|
||||
let bounds = this.openmct.time.bounds();
|
||||
let deltaTime = bounds.end - bounds.start;
|
||||
let newStart = bounds.start - percX * deltaTime;
|
||||
this.$emit('panAxis',{
|
||||
start: newStart,
|
||||
end: newStart + deltaTime
|
||||
});
|
||||
this.dragging = false;
|
||||
});
|
||||
})
|
||||
} else {
|
||||
console.log('Rejected drag due to RAF cap');
|
||||
}
|
||||
},
|
||||
dragEnd() {
|
||||
this.inPanMode ? this.endPan() : this.endZoom();
|
||||
|
||||
document.removeEventListener('mousemove', this.drag);
|
||||
this.dragStartX = undefined;
|
||||
this.dragX = undefined;
|
||||
},
|
||||
pan() {
|
||||
const panBounds = this.getPanBounds();
|
||||
this.$emit('panAxis', panBounds);
|
||||
},
|
||||
endPan() {
|
||||
const panBounds = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
|
||||
? this.getPanBounds()
|
||||
: undefined;
|
||||
this.$emit('endPan', panBounds);
|
||||
this.inPanMode = false;
|
||||
},
|
||||
getPanBounds() {
|
||||
const bounds = this.openmct.time.bounds();
|
||||
const deltaTime = bounds.end - bounds.start;
|
||||
const deltaX = this.dragX - this.dragStartX;
|
||||
const percX = deltaX / this.width;
|
||||
const panStart = bounds.start - percX * deltaTime;
|
||||
|
||||
return {
|
||||
start: panStart,
|
||||
end: panStart + deltaTime
|
||||
};
|
||||
},
|
||||
startZoom() {
|
||||
const x = this.scaleToBounds(this.dragStartX);
|
||||
|
||||
this.zoomStyle = {
|
||||
left: `${this.dragStartX - this.left}px`
|
||||
};
|
||||
|
||||
this.$emit('zoomAxis', {
|
||||
start: x,
|
||||
end: x
|
||||
this.openmct.time.bounds({
|
||||
start: this.bounds.start,
|
||||
end: this.bounds.end
|
||||
});
|
||||
},
|
||||
zoom() {
|
||||
const zoomRange = this.getZoomRange();
|
||||
|
||||
this.zoomStyle = {
|
||||
left: `${zoomRange.start - this.left}px`,
|
||||
width: `${zoomRange.end - zoomRange.start}px`
|
||||
};
|
||||
|
||||
this.$emit('zoomAxis', {
|
||||
start: this.scaleToBounds(zoomRange.start),
|
||||
end: this.scaleToBounds(zoomRange.end)
|
||||
});
|
||||
},
|
||||
endZoom() {
|
||||
const zoomRange = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
|
||||
? this.getZoomRange()
|
||||
: undefined;
|
||||
|
||||
const zoomBounds = zoomRange
|
||||
? {
|
||||
start: this.scaleToBounds(zoomRange.start),
|
||||
end: this.scaleToBounds(zoomRange.end)
|
||||
}
|
||||
: this.openmct.time.bounds();
|
||||
|
||||
this.zoomStyle = {};
|
||||
this.$emit('endZoom', zoomBounds);
|
||||
},
|
||||
getZoomRange() {
|
||||
const leftBound = this.left;
|
||||
const rightBound = this.left + this.width;
|
||||
|
||||
const zoomStart = this.dragX < leftBound
|
||||
? leftBound
|
||||
: Math.min(this.dragX, this.dragStartX);
|
||||
|
||||
const zoomEnd = this.dragX > rightBound
|
||||
? rightBound
|
||||
: Math.max(this.dragX, this.dragStartX);
|
||||
|
||||
return {
|
||||
start: zoomStart,
|
||||
end: zoomEnd
|
||||
};
|
||||
},
|
||||
scaleToBounds(value) {
|
||||
const bounds = this.openmct.time.bounds();
|
||||
const timeDelta = bounds.end - bounds.start;
|
||||
const valueDelta = value - this.left;
|
||||
const offset = valueDelta / this.width * timeDelta;
|
||||
return bounds.start + offset;
|
||||
},
|
||||
resize() {
|
||||
if (this.$refs.axisHolder.clientWidth !== this.width) {
|
||||
this.setAxisDimensions();
|
||||
this.width = this.$refs.axisHolder.clientWidth;
|
||||
this.setScale();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web 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 Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up">
|
||||
<button class="c-button--menu c-history-button icon-history"
|
||||
@click.prevent="toggle"
|
||||
>
|
||||
<span class="c-button__label">History</span>
|
||||
</button>
|
||||
<div v-if="open"
|
||||
class="c-menu c-conductor__history-menu"
|
||||
>
|
||||
<ul v-if="hasHistoryPresets">
|
||||
<li
|
||||
v-for="preset in presets"
|
||||
:key="preset.label"
|
||||
class="icon-clock"
|
||||
@click="selectPresetBounds(preset.bounds)"
|
||||
>
|
||||
{{ preset.label }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div
|
||||
v-if="hasHistoryPresets"
|
||||
class="c-menu__section-separator"
|
||||
></div>
|
||||
|
||||
<div class="c-menu__section-hint">
|
||||
Past timeframes, ordered by latest first
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
<li
|
||||
v-for="(timespan, index) in historyForCurrentTimeSystem"
|
||||
:key="index"
|
||||
class="icon-history"
|
||||
@click="selectTimespan(timespan)"
|
||||
>
|
||||
{{ formatTime(timespan.start) }} - {{ formatTime(timespan.end) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import toggleMixin from '../../ui/mixins/toggle-mixin';
|
||||
|
||||
const LOCAL_STORAGE_HISTORY_KEY = 'tcHistory';
|
||||
const DEFAULT_RECORDS = 10;
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'configuration'],
|
||||
mixins: [toggleMixin],
|
||||
props: {
|
||||
bounds: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
timeSystem: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
history: {}, // contains arrays of timespans {start, end}, array key is time system key
|
||||
presets: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasHistoryPresets() {
|
||||
return this.timeSystem.isUTCBased && this.presets.length;
|
||||
},
|
||||
historyForCurrentTimeSystem() {
|
||||
const history = this.history[this.timeSystem.key];
|
||||
|
||||
return history;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
bounds: {
|
||||
handler() {
|
||||
this.addTimespan();
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
timeSystem: {
|
||||
handler() {
|
||||
this.loadConfiguration();
|
||||
this.addTimespan();
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
history: {
|
||||
handler() {
|
||||
this.persistHistoryToLocalStorage();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getHistoryFromLocalStorage();
|
||||
},
|
||||
methods: {
|
||||
getHistoryFromLocalStorage() {
|
||||
if (localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY)) {
|
||||
this.history = JSON.parse(localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY))
|
||||
} else {
|
||||
this.history = {};
|
||||
this.persistHistoryToLocalStorage();
|
||||
}
|
||||
},
|
||||
persistHistoryToLocalStorage() {
|
||||
localStorage.setItem(LOCAL_STORAGE_HISTORY_KEY, JSON.stringify(this.history));
|
||||
},
|
||||
addTimespan() {
|
||||
const key = this.timeSystem.key;
|
||||
let [...currentHistory] = this.history[key] || [];
|
||||
const timespan = {
|
||||
start: this.bounds.start,
|
||||
end: this.bounds.end
|
||||
};
|
||||
|
||||
const isNotEqual = function (entry) {
|
||||
const start = entry.start !== this.start;
|
||||
const end = entry.end !== this.end;
|
||||
|
||||
return start || end;
|
||||
};
|
||||
currentHistory = currentHistory.filter(isNotEqual, timespan);
|
||||
|
||||
while (currentHistory.length >= this.records) {
|
||||
currentHistory.pop();
|
||||
}
|
||||
|
||||
currentHistory.unshift(timespan);
|
||||
this.history[key] = currentHistory;
|
||||
},
|
||||
selectTimespan(timespan) {
|
||||
this.openmct.time.bounds(timespan);
|
||||
},
|
||||
selectPresetBounds(bounds) {
|
||||
const start = typeof bounds.start === 'function' ? bounds.start() : bounds.start;
|
||||
const end = typeof bounds.end === 'function' ? bounds.end() : bounds.end;
|
||||
|
||||
this.selectTimespan({
|
||||
start: start,
|
||||
end: end
|
||||
});
|
||||
},
|
||||
loadConfiguration() {
|
||||
const configurations = this.configuration.menuOptions
|
||||
.filter(option => option.timeSystem === this.timeSystem.key);
|
||||
|
||||
this.presets = this.loadPresets(configurations);
|
||||
this.records = this.loadRecords(configurations);
|
||||
},
|
||||
loadPresets(configurations) {
|
||||
const configuration = configurations.find(option => option.presets);
|
||||
const presets = configuration ? configuration.presets : [];
|
||||
|
||||
return presets;
|
||||
},
|
||||
loadRecords(configurations) {
|
||||
const configuration = configurations.find(option => option.records);
|
||||
const records = configuration ? configuration.records : DEFAULT_RECORDS;
|
||||
|
||||
return records;
|
||||
},
|
||||
formatTime(time) {
|
||||
const formatter = this.openmct.telemetry.getValueFormatter({
|
||||
format: this.timeSystem.timeFormat
|
||||
}).formatter;
|
||||
|
||||
return formatter.format(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -110,7 +110,7 @@ export default {
|
||||
if (clock === undefined) {
|
||||
return {
|
||||
key: 'fixed',
|
||||
name: 'Fixed Timespan',
|
||||
name: 'Fixed Timespan Mode',
|
||||
description: 'Query and explore data that falls between two fixed datetimes.',
|
||||
cssClass: 'icon-tabular'
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
text-rendering: geometricPrecision;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
> g.axis {
|
||||
> g {
|
||||
// Overall Tick holder
|
||||
transform: translateY($tickYPos);
|
||||
path {
|
||||
@@ -44,6 +44,7 @@
|
||||
}
|
||||
|
||||
body.desktop .is-fixed-mode & {
|
||||
@include cursorGrab();
|
||||
background-size: 3px 30%;
|
||||
background-color: $colorBodyBgSubtle;
|
||||
box-shadow: inset rgba(black, 0.4) 0 1px 1px;
|
||||
@@ -54,6 +55,17 @@
|
||||
stroke: $colorBodyBgSubtle;
|
||||
transition: $transOut;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active {
|
||||
$c: $colorKeySubtle;
|
||||
background-color: $c;
|
||||
transition: $transIn;
|
||||
svg text {
|
||||
stroke: $c;
|
||||
transition: $transIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-realtime-mode & {
|
||||
|
||||
@@ -57,65 +57,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.is-fixed-mode {
|
||||
.c-conductor-axis {
|
||||
&__zoom-indicator {
|
||||
border: 1px solid transparent;
|
||||
display: none; // Hidden by default
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.is-panning),
|
||||
&:not(.is-zooming) {
|
||||
.c-conductor-axis {
|
||||
&:hover,
|
||||
&:active {
|
||||
cursor: col-resize;
|
||||
filter: $timeConductorAxisHoverFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-panning,
|
||||
&.is-zooming {
|
||||
.c-conductor-input input {
|
||||
// Styles for inputs while zooming or panning
|
||||
background: rgba($timeConductorActiveBg, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
&.alt-pressed {
|
||||
.c-conductor-axis:hover {
|
||||
// When alt is being pressed and user is hovering over the axis, set the cursor
|
||||
@include cursorGrab();
|
||||
}
|
||||
}
|
||||
|
||||
&.is-panning {
|
||||
.c-conductor-axis {
|
||||
@include cursorGrab();
|
||||
background-color: $timeConductorActivePanBg;
|
||||
transition: $transIn;
|
||||
|
||||
svg text {
|
||||
stroke: $timeConductorActivePanBg;
|
||||
transition: $transIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-zooming {
|
||||
.c-conductor-axis__zoom-indicator {
|
||||
display: block;
|
||||
position: absolute;
|
||||
background: rgba($timeConductorActiveBg, 0.4);
|
||||
border-left-color: $timeConductorActiveBg;
|
||||
border-right-color: $timeConductorActiveBg;
|
||||
top: 0; bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-realtime-mode {
|
||||
.c-conductor__time-bounds {
|
||||
grid-template-columns: 20px auto 1fr auto auto;
|
||||
|
||||
@@ -142,9 +142,6 @@ $colorTimeHov: pullForward($colorTime, 10%);
|
||||
$colorTimeSubtle: pushBack($colorTime, 20%);
|
||||
$colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
|
||||
$colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
|
||||
$timeConductorAxisHoverFilter: brightness(1.2);
|
||||
$timeConductorActiveBg: $colorKey;
|
||||
$timeConductorActivePanBg: #226074;
|
||||
|
||||
/************************************************** BROWSING */
|
||||
$browseFrameColor: pullForward($colorBodyBg, 10%);
|
||||
|
||||
@@ -146,9 +146,6 @@ $colorTimeHov: pullForward($colorTime, 10%);
|
||||
$colorTimeSubtle: pushBack($colorTime, 20%);
|
||||
$colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
|
||||
$colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
|
||||
$timeConductorAxisHoverFilter: brightness(1.2);
|
||||
$timeConductorActiveBg: $colorKey;
|
||||
$timeConductorActivePanBg: #226074;
|
||||
|
||||
/************************************************** BROWSING */
|
||||
$browseFrameColor: pullForward($colorBodyBg, 10%);
|
||||
|
||||
@@ -132,7 +132,7 @@ $colorPausedFg: #fff;
|
||||
// Base variations
|
||||
$colorBodyBgSubtle: pullForward($colorBodyBg, 5%);
|
||||
$colorBodyBgSubtleHov: pushBack($colorKey, 50%);
|
||||
$colorKeySubtle: pushBack($colorKey, 20%);
|
||||
$colorKeySubtle: pushBack($colorKey, 10%);
|
||||
|
||||
// Time Colors
|
||||
$colorTime: #618cff;
|
||||
@@ -142,9 +142,6 @@ $colorTimeHov: pushBack($colorTime, 5%);
|
||||
$colorTimeSubtle: pushBack($colorTime, 20%);
|
||||
$colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
|
||||
$colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
|
||||
$timeConductorAxisHoverFilter: brightness(0.8);
|
||||
$timeConductorActiveBg: $colorKey;
|
||||
$timeConductorActivePanBg: #A0CDE1;
|
||||
|
||||
/************************************************** BROWSING */
|
||||
$browseFrameColor: pullForward($colorBodyBg, 10%);
|
||||
|
||||
@@ -462,17 +462,9 @@ select {
|
||||
text-shadow: $shdwMenuText;
|
||||
padding: $interiorMarginSm;
|
||||
box-shadow: $shdwMenu;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
//+ * {
|
||||
// margin-top: $interiorMarginSm;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin menuInner() {
|
||||
@@ -510,23 +502,6 @@ select {
|
||||
.c-menu {
|
||||
@include menuOuter();
|
||||
@include menuInner();
|
||||
|
||||
&__section-hint {
|
||||
$m: $interiorMargin;
|
||||
margin: $m 0;
|
||||
padding: $m nth($menuItemPad, 2) 0 nth($menuItemPad, 2);
|
||||
|
||||
opacity: 0.6;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
&__section-separator {
|
||||
$m: $interiorMargin;
|
||||
border-top: 1px solid $colorInteriorBorder;
|
||||
margin: $m 0;
|
||||
padding: $m nth($menuItemPad, 2) 0 nth($menuItemPad, 2);
|
||||
}
|
||||
}
|
||||
|
||||
.c-super-menu {
|
||||
@@ -590,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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
@mixin visibleRegexButton {
|
||||
opacity: 1;
|
||||
padding: 1px 3px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.c-search {
|
||||
@include wrappedInput();
|
||||
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
|
||||
@@ -14,46 +9,11 @@
|
||||
content: $glyph-icon-magnify;
|
||||
}
|
||||
|
||||
&__use-regex {
|
||||
// Button
|
||||
$c: $colorBodyFg;
|
||||
background: rgba($c, 0.2);
|
||||
border: 1px solid rgba($c, 0.3);
|
||||
color: $c;
|
||||
border-radius: $controlCr;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
font-size: 0.8em;
|
||||
margin-left: $interiorMarginSm;
|
||||
min-width: 0;
|
||||
opacity: 0;
|
||||
order: 2;
|
||||
overflow: hidden;
|
||||
padding: 1px 0;
|
||||
transform-origin: left;
|
||||
transition: $transOut;
|
||||
width: 0;
|
||||
|
||||
&.is-active {
|
||||
$c: $colorBtnActiveBg;
|
||||
@include visibleRegexButton();
|
||||
background: rgba($c, 0.3);
|
||||
border-color: $c;
|
||||
color: $c;
|
||||
}
|
||||
}
|
||||
|
||||
&__clear-input {
|
||||
display: none;
|
||||
order: 99;
|
||||
padding: 1px 0;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
.c-search__use-regex {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.c-search__clear-input {
|
||||
display: block;
|
||||
}
|
||||
@@ -61,15 +21,6 @@
|
||||
|
||||
input[type='text'],
|
||||
input[type='search'] {
|
||||
margin-left: $interiorMargin;
|
||||
order: 3;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.c-search__use-regex {
|
||||
@include visibleRegexButton();
|
||||
transition: $transIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
class="c-search__clear-input icon-x-in-circle"
|
||||
@click="clearInput"
|
||||
></a>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -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">
|
||||
@@ -198,8 +199,6 @@ export default {
|
||||
updateName(event) {
|
||||
if (event.target.innerText !== this.domainObject.name && event.target.innerText.match(/\S/)) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'name', event.target.innerText);
|
||||
} else {
|
||||
event.target.innerText = this.domainObject.name;
|
||||
}
|
||||
},
|
||||
updateNameOnEnterKeyPress(event) {
|
||||
|
||||
@@ -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