mirror of
https://github.com/nasa/openmct.git
synced 2025-06-30 12:43:04 +00:00
Compare commits
31 Commits
adding-uni
...
couchdb-te
Author | SHA1 | Date | |
---|---|---|---|
a5c61ec1b7 | |||
7e7141a5a0 | |||
f6ecabb053 | |||
831f207b10 | |||
42e474ca60 | |||
d767932be2 | |||
0238a86be5 | |||
7abbd7cb20 | |||
6e2b12b00d | |||
e32f465f7a | |||
abc458cef4 | |||
6a2520f39b | |||
5b7a011069 | |||
b76d4b76cb | |||
5a4cba0226 | |||
f03bfdebb4 | |||
d216117b30 | |||
5c520bfce9 | |||
cba9670823 | |||
27651e9eaa | |||
f096d54dd0 | |||
13ff0c368d | |||
8258f21f7b | |||
44bfcf33ef | |||
669415d362 | |||
8601ec441f | |||
9a57a20404 | |||
1a3bff9813 | |||
baa5f21640 | |||
af9dceee3c | |||
b7d2402434 |
@ -11,12 +11,12 @@ jobs:
|
|||||||
name: Update npm
|
name: Update npm
|
||||||
command: 'sudo npm install -g npm@latest'
|
command: 'sudo npm install -g npm@latest'
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-13-{{ checksum "package.json" }}
|
key: dependency-cache-{{ checksum "package.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Installing dependencies (npm install)
|
name: Installing dependencies (npm install)
|
||||||
command: npm install
|
command: npm install
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: dependency-cache-13-{{ checksum "package.json" }}
|
key: dependency-cache-{{ checksum "package.json" }}
|
||||||
paths:
|
paths:
|
||||||
- node_modules
|
- node_modules
|
||||||
- run:
|
- run:
|
||||||
|
@ -41,6 +41,7 @@ define([
|
|||||||
{
|
{
|
||||||
key: "sin",
|
key: "sin",
|
||||||
name: "Sine",
|
name: "Sine",
|
||||||
|
unit: "Hz",
|
||||||
formatString: '%0.2f',
|
formatString: '%0.2f',
|
||||||
hints: {
|
hints: {
|
||||||
range: 1
|
range: 1
|
||||||
@ -49,6 +50,7 @@ define([
|
|||||||
{
|
{
|
||||||
key: "cos",
|
key: "cos",
|
||||||
name: "Cosine",
|
name: "Cosine",
|
||||||
|
unit: "deg",
|
||||||
formatString: '%0.2f',
|
formatString: '%0.2f',
|
||||||
hints: {
|
hints: {
|
||||||
range: 2
|
range: 2
|
||||||
|
3
indexTest.js
Normal file
3
indexTest.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
const testsContext = require.context('.', true, /\/(src|platform)\/.*Spec.js$/);
|
||||||
|
|
||||||
|
testsContext.keys().forEach(testsContext);
|
@ -23,7 +23,7 @@
|
|||||||
/*global module,process*/
|
/*global module,process*/
|
||||||
|
|
||||||
const devMode = process.env.NODE_ENV !== 'production';
|
const devMode = process.env.NODE_ENV !== 'production';
|
||||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'FirefoxHeadless'];
|
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless'];
|
||||||
const coverageEnabled = process.env.COVERAGE === 'true';
|
const coverageEnabled = process.env.COVERAGE === 'true';
|
||||||
const reporters = ['progress', 'html'];
|
const reporters = ['progress', 'html'];
|
||||||
|
|
||||||
@ -52,12 +52,16 @@ module.exports = (config) => {
|
|||||||
basePath: '',
|
basePath: '',
|
||||||
frameworks: ['jasmine'],
|
frameworks: ['jasmine'],
|
||||||
files: [
|
files: [
|
||||||
'platform/**/*Spec.js',
|
'indexTest.js'
|
||||||
'src/**/*Spec.js'
|
|
||||||
],
|
],
|
||||||
port: 9876,
|
port: 9876,
|
||||||
reporters: reporters,
|
reporters: reporters,
|
||||||
browsers: browsers,
|
browsers: browsers,
|
||||||
|
client: {
|
||||||
|
jasmine: {
|
||||||
|
random: false
|
||||||
|
}
|
||||||
|
},
|
||||||
customLaunchers: {
|
customLaunchers: {
|
||||||
ChromeDebugging: {
|
ChromeDebugging: {
|
||||||
base: 'Chrome',
|
base: 'Chrome',
|
||||||
@ -66,7 +70,7 @@ module.exports = (config) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
colors: true,
|
colors: true,
|
||||||
logLevel: config.LOG_INFO,
|
logLevel: config.LOG_DEBUG,
|
||||||
autoWatch: true,
|
autoWatch: true,
|
||||||
// HTML test reporting.
|
// HTML test reporting.
|
||||||
htmlReporter: {
|
htmlReporter: {
|
||||||
@ -82,20 +86,20 @@ module.exports = (config) => {
|
|||||||
reports: ['html', 'lcovonly', 'text-summary'],
|
reports: ['html', 'lcovonly', 'text-summary'],
|
||||||
thresholds: {
|
thresholds: {
|
||||||
global: {
|
global: {
|
||||||
lines: 62
|
lines: 64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
'platform/**/*Spec.js': ['webpack', 'sourcemap'],
|
'indexTest.js': ['webpack', 'sourcemap']
|
||||||
'src/**/*Spec.js': ['webpack', 'sourcemap']
|
|
||||||
},
|
},
|
||||||
webpack: webpackConfig,
|
webpack: webpackConfig,
|
||||||
webpackMiddleware: {
|
webpackMiddleware: {
|
||||||
stats: 'errors-only',
|
stats: 'errors-only',
|
||||||
logLevel: 'warn'
|
logLevel: 'warn'
|
||||||
},
|
},
|
||||||
|
concurrency: 1,
|
||||||
singleRun: true,
|
singleRun: true,
|
||||||
browserNoActivityTimeout: 90000
|
browserNoActivityTimeout: 90000
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
20
package.json
20
package.json
@ -39,16 +39,16 @@
|
|||||||
"istanbul-instrumenter-loader": "^3.0.1",
|
"istanbul-instrumenter-loader": "^3.0.1",
|
||||||
"jasmine-core": "^3.1.0",
|
"jasmine-core": "^3.1.0",
|
||||||
"jsdoc": "^3.3.2",
|
"jsdoc": "^3.3.2",
|
||||||
"karma": "^2.0.3",
|
"karma": "5.1.1",
|
||||||
"karma-chrome-launcher": "^2.2.0",
|
"karma-chrome-launcher": "3.1.0",
|
||||||
"karma-firefox-launcher": "^1.3.0",
|
"karma-firefox-launcher": "1.3.0",
|
||||||
"karma-cli": "^1.0.1",
|
"karma-cli": "2.0.0",
|
||||||
"karma-coverage": "^1.1.2",
|
"karma-coverage": "2.0.3",
|
||||||
"karma-coverage-istanbul-reporter": "^2.1.1",
|
"karma-coverage-istanbul-reporter": "3.0.3",
|
||||||
"karma-html-reporter": "^0.2.7",
|
"karma-html-reporter": "0.2.7",
|
||||||
"karma-jasmine": "^1.1.2",
|
"karma-jasmine": "3.3.1",
|
||||||
"karma-sourcemap-loader": "^0.3.7",
|
"karma-sourcemap-loader": "0.3.7",
|
||||||
"karma-webpack": "^3.0.0",
|
"karma-webpack": "4.0.2",
|
||||||
"location-bar": "^3.0.1",
|
"location-bar": "^3.0.1",
|
||||||
"lodash": "^4.17.12",
|
"lodash": "^4.17.12",
|
||||||
"markdown-toc": "^0.11.7",
|
"markdown-toc": "^0.11.7",
|
||||||
|
@ -79,12 +79,6 @@ function (
|
|||||||
return this.objectService;
|
return this.objectService;
|
||||||
};
|
};
|
||||||
|
|
||||||
function resolveWith(object) {
|
|
||||||
return function () {
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save changes and conclude editing.
|
* Save changes and conclude editing.
|
||||||
*
|
*
|
||||||
@ -102,7 +96,6 @@ function (
|
|||||||
SaveAsAction.prototype.save = function () {
|
SaveAsAction.prototype.save = function () {
|
||||||
var self = this,
|
var self = this,
|
||||||
domainObject = this.domainObject,
|
domainObject = this.domainObject,
|
||||||
copyService = this.copyService,
|
|
||||||
dialog = new SaveInProgressDialog(this.dialogService),
|
dialog = new SaveInProgressDialog(this.dialogService),
|
||||||
toUndirty = [];
|
toUndirty = [];
|
||||||
|
|
||||||
@ -139,19 +132,22 @@ function (
|
|||||||
return fetchObject(object.getModel().location);
|
return fetchObject(object.getModel().location);
|
||||||
}
|
}
|
||||||
|
|
||||||
function allowClone(objectToClone) {
|
function saveObject(parent) {
|
||||||
var allowed =
|
return this.openmct.editor.save().then(() => {
|
||||||
(objectToClone.getId() === domainObject.getId())
|
// Force mutation for search indexing
|
||||||
|| objectToClone.getCapability('location').isOriginal();
|
return parent;
|
||||||
if (allowed) {
|
});
|
||||||
toUndirty.push(objectToClone);
|
|
||||||
}
|
|
||||||
|
|
||||||
return allowed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cloneIntoParent(parent) {
|
function addSavedObjectToParent(parent) {
|
||||||
return copyService.perform(domainObject, parent, allowClone);
|
return parent.getCapability("composition")
|
||||||
|
.add(domainObject)
|
||||||
|
.then(function (addedObject) {
|
||||||
|
return parent.getCapability("persistence").persist()
|
||||||
|
.then(function () {
|
||||||
|
return addedObject;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function undirty(object) {
|
function undirty(object) {
|
||||||
@ -160,26 +156,17 @@ function (
|
|||||||
|
|
||||||
function undirtyOriginals(object) {
|
function undirtyOriginals(object) {
|
||||||
return Promise.all(toUndirty.map(undirty))
|
return Promise.all(toUndirty.map(undirty))
|
||||||
.then(resolveWith(object));
|
.then(() => {
|
||||||
|
return object;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAfterClone(clonedObject) {
|
function indexForSearch(addedObject) {
|
||||||
return this.openmct.editor.save().then(() => {
|
addedObject.useCapability('mutation', (model) => {
|
||||||
// Force mutation for search indexing
|
|
||||||
return clonedObject;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function finishEditing(clonedObject) {
|
|
||||||
return fetchObject(clonedObject.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
function indexForSearch(savedObject) {
|
|
||||||
savedObject.useCapability('mutation', (model) => {
|
|
||||||
return model;
|
return model;
|
||||||
});
|
});
|
||||||
|
|
||||||
return savedObject;
|
return addedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSuccess(object) {
|
function onSuccess(object) {
|
||||||
@ -201,10 +188,12 @@ function (
|
|||||||
.then(doWizardSave)
|
.then(doWizardSave)
|
||||||
.then(showBlockingDialog)
|
.then(showBlockingDialog)
|
||||||
.then(getParent)
|
.then(getParent)
|
||||||
.then(cloneIntoParent)
|
.then(saveObject)
|
||||||
|
.then(addSavedObjectToParent)
|
||||||
.then(undirtyOriginals)
|
.then(undirtyOriginals)
|
||||||
.then(saveAfterClone)
|
.then((addedObject) => {
|
||||||
.then(finishEditing)
|
return fetchObject(addedObject.getId());
|
||||||
|
})
|
||||||
.then(indexForSearch)
|
.then(indexForSearch)
|
||||||
.then(hideBlockingDialog)
|
.then(hideBlockingDialog)
|
||||||
.then(onSuccess)
|
.then(onSuccess)
|
||||||
|
@ -28,6 +28,7 @@ define(
|
|||||||
describe("The Transaction Service", function () {
|
describe("The Transaction Service", function () {
|
||||||
var mockQ,
|
var mockQ,
|
||||||
mockLog,
|
mockLog,
|
||||||
|
mockCacheService,
|
||||||
transactionService;
|
transactionService;
|
||||||
|
|
||||||
function fastPromise(val) {
|
function fastPromise(val) {
|
||||||
@ -40,9 +41,10 @@ define(
|
|||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockQ = jasmine.createSpyObj("$q", ["all"]);
|
mockQ = jasmine.createSpyObj("$q", ["all"]);
|
||||||
|
mockCacheService = jasmine.createSpyObj("cacheService", ["flush"]);
|
||||||
mockQ.all.and.returnValue(fastPromise());
|
mockQ.all.and.returnValue(fastPromise());
|
||||||
mockLog = jasmine.createSpyObj("$log", ["error"]);
|
mockLog = jasmine.createSpyObj("$log", ["error"]);
|
||||||
transactionService = new TransactionService(mockQ, mockLog);
|
transactionService = new TransactionService(mockQ, mockLog, mockCacheService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("isActive returns true if a transaction is in progress", function () {
|
it("isActive returns true if a transaction is in progress", function () {
|
||||||
@ -85,17 +87,20 @@ define(
|
|||||||
|
|
||||||
it("commit calls all queued commit functions", function () {
|
it("commit calls all queued commit functions", function () {
|
||||||
expect(transactionService.size()).toBe(3);
|
expect(transactionService.size()).toBe(3);
|
||||||
transactionService.commit();
|
|
||||||
onCommits.forEach(function (spy) {
|
return transactionService.commit().then(() => {
|
||||||
expect(spy).toHaveBeenCalled();
|
onCommits.forEach(function (spy) {
|
||||||
|
expect(spy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("commit resets active state and clears queues", function () {
|
it("commit resets active state and clears queues", function () {
|
||||||
transactionService.commit();
|
return transactionService.commit().then(() => {
|
||||||
expect(transactionService.isActive()).toBe(false);
|
expect(transactionService.isActive()).toBe(false);
|
||||||
expect(transactionService.size()).toBe(0);
|
expect(transactionService.size()).toBe(0);
|
||||||
expect(transactionService.size()).toBe(0);
|
expect(transactionService.size()).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -46,25 +46,34 @@ define([
|
|||||||
spyOn(provider, 'cleanTerm').and.returnValue('cleanedTerm');
|
spyOn(provider, 'cleanTerm').and.returnValue('cleanedTerm');
|
||||||
spyOn(provider, 'fuzzyMatchUnquotedTerms').and.returnValue('fuzzy');
|
spyOn(provider, 'fuzzyMatchUnquotedTerms').and.returnValue('fuzzy');
|
||||||
spyOn(provider, 'parseResponse').and.returnValue('parsedResponse');
|
spyOn(provider, 'parseResponse').and.returnValue('parsedResponse');
|
||||||
$http.and.returnValue(Promise.resolve({}));
|
$http.and.returnValue(Promise.resolve({
|
||||||
|
data: {
|
||||||
|
hits: {
|
||||||
|
hits: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('cleans terms and adds fuzzyness', function () {
|
it('cleans terms and adds fuzzyness', function () {
|
||||||
provider.query('hello', 10);
|
return provider.query('hello', 10)
|
||||||
expect(provider.cleanTerm).toHaveBeenCalledWith('hello');
|
.then(() => {
|
||||||
expect(provider.fuzzyMatchUnquotedTerms)
|
expect(provider.cleanTerm).toHaveBeenCalledWith('hello');
|
||||||
.toHaveBeenCalledWith('cleanedTerm');
|
expect(provider.fuzzyMatchUnquotedTerms)
|
||||||
|
.toHaveBeenCalledWith('cleanedTerm');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls through to $http', function () {
|
it('calls through to $http', function () {
|
||||||
provider.query('hello', 10);
|
return provider.query('hello', 10).then(() => {
|
||||||
expect($http).toHaveBeenCalledWith({
|
expect($http).toHaveBeenCalledWith({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
params: {
|
params: {
|
||||||
q: 'fuzzy',
|
q: 'fuzzy',
|
||||||
size: 10
|
size: 10
|
||||||
},
|
},
|
||||||
url: 'http://localhost:9200/_search/'
|
url: 'http://localhost:9200/_search/'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ define([
|
|||||||
"../../src/services/SearchAggregator"
|
"../../src/services/SearchAggregator"
|
||||||
], function (SearchAggregator) {
|
], function (SearchAggregator) {
|
||||||
|
|
||||||
describe("SearchAggregator", function () {
|
xdescribe("SearchAggregator", function () {
|
||||||
var $q,
|
var $q,
|
||||||
objectService,
|
objectService,
|
||||||
providers,
|
providers,
|
||||||
|
@ -422,7 +422,10 @@ define([
|
|||||||
|
|
||||||
this.router.start();
|
this.router.start();
|
||||||
this.emit('start');
|
this.emit('start');
|
||||||
}.bind(this));
|
}.bind(this), function () {
|
||||||
|
console.log('startPromise failed');
|
||||||
|
this.emit('start');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
MCT.prototype.startHeadless = function () {
|
MCT.prototype.startHeadless = function () {
|
||||||
@ -444,6 +447,7 @@ define([
|
|||||||
|
|
||||||
MCT.prototype.destroy = function () {
|
MCT.prototype.destroy = function () {
|
||||||
this.emit('destroy');
|
this.emit('destroy');
|
||||||
|
this.router.destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
MCT.prototype.plugins = plugins;
|
MCT.prototype.plugins = plugins;
|
||||||
|
@ -32,10 +32,6 @@ define([
|
|||||||
var mockListener;
|
var mockListener;
|
||||||
var oldBundles;
|
var oldBundles;
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
testUtils.resetApplicationState();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockPlugin = jasmine.createSpy('plugin');
|
mockPlugin = jasmine.createSpy('plugin');
|
||||||
mockPlugin2 = jasmine.createSpy('plugin2');
|
mockPlugin2 = jasmine.createSpy('plugin2');
|
||||||
@ -56,7 +52,8 @@ define([
|
|||||||
legacyRegistry.delete(bundle);
|
legacyRegistry.delete(bundle);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
testUtils.resetApplicationState(openmct);
|
|
||||||
|
return testUtils.resetApplicationState(openmct);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("exposes plugins", function () {
|
it("exposes plugins", function () {
|
||||||
|
@ -35,7 +35,8 @@ define([
|
|||||||
'./services/LegacyObjectAPIInterceptor',
|
'./services/LegacyObjectAPIInterceptor',
|
||||||
'./views/installLegacyViews',
|
'./views/installLegacyViews',
|
||||||
'./policies/LegacyCompositionPolicyAdapter',
|
'./policies/LegacyCompositionPolicyAdapter',
|
||||||
'./actions/LegacyActionAdapter'
|
'./actions/LegacyActionAdapter',
|
||||||
|
'./services/LegacyPersistenceAdapter'
|
||||||
], function (
|
], function (
|
||||||
ActionDialogDecorator,
|
ActionDialogDecorator,
|
||||||
AdapterCapability,
|
AdapterCapability,
|
||||||
@ -51,7 +52,8 @@ define([
|
|||||||
LegacyObjectAPIInterceptor,
|
LegacyObjectAPIInterceptor,
|
||||||
installLegacyViews,
|
installLegacyViews,
|
||||||
legacyCompositionPolicyAdapter,
|
legacyCompositionPolicyAdapter,
|
||||||
LegacyActionAdapter
|
LegacyActionAdapter,
|
||||||
|
LegacyPersistenceAdapter
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
name: 'src/adapter',
|
name: 'src/adapter',
|
||||||
@ -114,6 +116,13 @@ define([
|
|||||||
"instantiate",
|
"instantiate",
|
||||||
"topic"
|
"topic"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provides: "persistenceService",
|
||||||
|
type: "provider",
|
||||||
|
priority: "fallback",
|
||||||
|
implementation: LegacyPersistenceAdapter.default,
|
||||||
|
depends: ["openmct"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
policies: [
|
policies: [
|
||||||
|
29
src/adapter/services/LegacyPersistenceAdapter.js
Normal file
29
src/adapter/services/LegacyPersistenceAdapter.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import objectUtils from 'objectUtils';
|
||||||
|
|
||||||
|
function LegacyPersistenceProvider(openmct) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
}
|
||||||
|
|
||||||
|
LegacyPersistenceProvider.prototype.listObjects = function () {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
LegacyPersistenceProvider.prototype.listSpaces = function () {
|
||||||
|
return Promise.resolve(Object.keys(this.openmct.objects.providers));
|
||||||
|
};
|
||||||
|
|
||||||
|
LegacyPersistenceProvider.prototype.updateObject = function (legacyDomainObject) {
|
||||||
|
return this.openmct.objects.save(legacyDomainObject.useCapability('adapter'));
|
||||||
|
};
|
||||||
|
|
||||||
|
LegacyPersistenceProvider.prototype.updateObject = function (legacyDomainObject) {
|
||||||
|
return this.openmct.objects.save(legacyDomainObject.useCapability('adapter'));
|
||||||
|
};
|
||||||
|
|
||||||
|
LegacyPersistenceProvider.prototype.readObject = function (keystring) {
|
||||||
|
let identifier = objectUtils.parseKeyString(keystring);
|
||||||
|
|
||||||
|
return this.openmct.legacyObject(this.openmct.objects.get(identifier));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LegacyPersistenceProvider;
|
@ -32,6 +32,12 @@
|
|||||||
class="js-third-data"
|
class="js-third-data"
|
||||||
:class="valueClass"
|
:class="valueClass"
|
||||||
>{{ value }}</td>
|
>{{ value }}</td>
|
||||||
|
<td
|
||||||
|
v-if="hasUnits"
|
||||||
|
class="js-units"
|
||||||
|
>
|
||||||
|
{{ unit }}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -48,6 +54,10 @@ export default {
|
|||||||
domainObject: {
|
domainObject: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
hasUnits: {
|
||||||
|
type: Boolean,
|
||||||
|
requred: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -59,7 +69,8 @@ export default {
|
|||||||
timestamp: undefined,
|
timestamp: undefined,
|
||||||
value: '---',
|
value: '---',
|
||||||
valueClass: '',
|
valueClass: '',
|
||||||
currentObjectPath
|
currentObjectPath,
|
||||||
|
unit: ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -101,6 +112,10 @@ export default {
|
|||||||
.subscribe(this.domainObject, this.updateValues);
|
.subscribe(this.domainObject, this.updateValues);
|
||||||
|
|
||||||
this.requestHistory();
|
this.requestHistory();
|
||||||
|
|
||||||
|
if (this.hasUnits) {
|
||||||
|
this.setUnit();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.stopWatchingMutation();
|
this.stopWatchingMutation();
|
||||||
@ -186,6 +201,9 @@ export default {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setUnit() {
|
||||||
|
this.unit = this.valueMetadata.unit || '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Timestamp</th>
|
<th>Timestamp</th>
|
||||||
<th>Value</th>
|
<th>Value</th>
|
||||||
|
<th v-if="hasUnits">Unit</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -35,6 +36,7 @@
|
|||||||
v-for="item in items"
|
v-for="item in items"
|
||||||
:key="item.key"
|
:key="item.key"
|
||||||
:domain-object="item.domainObject"
|
:domain-object="item.domainObject"
|
||||||
|
:has-units="hasUnits"
|
||||||
/>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -54,6 +56,18 @@ export default {
|
|||||||
items: []
|
items: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
hasUnits() {
|
||||||
|
let itemsWithUnits = this.items.filter((item) => {
|
||||||
|
let metadata = this.openmct.telemetry.getMetadata(item.domainObject);
|
||||||
|
|
||||||
|
return this.metadataHasUnits(metadata.valueMetadatas);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return itemsWithUnits.length !== 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.composition = this.openmct.composition.get(this.domainObject);
|
this.composition = this.openmct.composition.get(this.domainObject);
|
||||||
this.composition.on('add', this.addItem);
|
this.composition.on('add', this.addItem);
|
||||||
@ -84,6 +98,11 @@ export default {
|
|||||||
reorderPlan.forEach((reorderEvent) => {
|
reorderPlan.forEach((reorderEvent) => {
|
||||||
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
metadataHasUnits(valueMetadatas) {
|
||||||
|
let metadataWithUnits = valueMetadatas.filter(metadatum => metadatum.unit);
|
||||||
|
|
||||||
|
return metadataWithUnits.length > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Timestamp</th>
|
<th>Timestamp</th>
|
||||||
<th>Value</th>
|
<th>Value</th>
|
||||||
|
<th v-if="hasUnits">Unit</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -45,6 +46,7 @@
|
|||||||
v-for="secondary in secondaryTelemetryObjects[primary.key]"
|
v-for="secondary in secondaryTelemetryObjects[primary.key]"
|
||||||
:key="secondary.key"
|
:key="secondary.key"
|
||||||
:domain-object="secondary.domainObject"
|
:domain-object="secondary.domainObject"
|
||||||
|
:has-units="hasUnits"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -66,6 +68,23 @@ export default {
|
|||||||
compositions: []
|
compositions: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
hasUnits() {
|
||||||
|
let ladTables = Object.values(this.secondaryTelemetryObjects);
|
||||||
|
for (let ladTable of ladTables) {
|
||||||
|
for (let telemetryObject of ladTable) {
|
||||||
|
let metadata = this.openmct.telemetry.getMetadata(telemetryObject.domainObject);
|
||||||
|
for (let metadatum of metadata.valueMetadatas) {
|
||||||
|
if (metadatum.unit) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.composition = this.openmct.composition.get(this.domainObject);
|
this.composition = this.openmct.composition.get(this.domainObject);
|
||||||
this.composition.on('add', this.addPrimary);
|
this.composition.on('add', this.addPrimary);
|
||||||
@ -109,9 +128,8 @@ export default {
|
|||||||
let index = this.primaryTelemetryObjects.findIndex(primary => this.openmct.objects.makeKeyString(identifier) === primary.key),
|
let index = this.primaryTelemetryObjects.findIndex(primary => this.openmct.objects.makeKeyString(identifier) === primary.key),
|
||||||
primary = this.primaryTelemetryObjects[index];
|
primary = this.primaryTelemetryObjects[index];
|
||||||
|
|
||||||
this.$set(this.secondaryTelemetryObjects, primary.key, undefined);
|
this.$delete(this.secondaryTelemetryObjects, primary.key);
|
||||||
this.primaryTelemetryObjects.splice(index, 1);
|
this.primaryTelemetryObjects.splice(index, 1);
|
||||||
primary = undefined;
|
|
||||||
},
|
},
|
||||||
reorderPrimary(reorderPlan) {
|
reorderPrimary(reorderPlan) {
|
||||||
let oldComposition = this.primaryTelemetryObjects.slice();
|
let oldComposition = this.primaryTelemetryObjects.slice();
|
||||||
|
@ -94,7 +94,7 @@ describe("The LAD Table", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
resetApplicationState(openmct);
|
return resetApplicationState(openmct);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should provide a table view only for lad table objects", () => {
|
it("should provide a table view only for lad table objects", () => {
|
||||||
@ -284,7 +284,7 @@ describe("The LAD Table Set", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
resetApplicationState(openmct);
|
return resetApplicationState(openmct);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should provide a lad table set view only for lad table set objects", () => {
|
it("should provide a lad table set view only for lad table set objects", () => {
|
||||||
|
@ -35,7 +35,7 @@ define(
|
|||||||
) {
|
) {
|
||||||
var defaultAjaxFunction = $.ajax;
|
var defaultAjaxFunction = $.ajax;
|
||||||
|
|
||||||
xdescribe("The URLIndicator", function () {
|
describe("The URLIndicator", function () {
|
||||||
var openmct;
|
var openmct;
|
||||||
var indicatorElement;
|
var indicatorElement;
|
||||||
var pluginOptions;
|
var pluginOptions;
|
||||||
|
@ -66,7 +66,7 @@ export default class URLTimeSettingsSynchronizer {
|
|||||||
TIME_EVENTS.forEach(event => {
|
TIME_EVENTS.forEach(event => {
|
||||||
this.openmct.time.off(event, this.setUrlFromTimeApi);
|
this.openmct.time.off(event, this.setUrlFromTimeApi);
|
||||||
});
|
});
|
||||||
this.openmct.time.on('bounds', this.updateBounds);
|
this.openmct.time.off('bounds', this.updateBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTimeSettings() {
|
updateTimeSettings() {
|
||||||
|
@ -27,7 +27,6 @@ import {
|
|||||||
describe("The URLTimeSettingsSynchronizer", () => {
|
describe("The URLTimeSettingsSynchronizer", () => {
|
||||||
let openmct;
|
let openmct;
|
||||||
let testClock;
|
let testClock;
|
||||||
beforeAll(() => resetApplicationState());
|
|
||||||
|
|
||||||
beforeEach((done) => {
|
beforeEach((done) => {
|
||||||
openmct = createOpenMct();
|
openmct = createOpenMct();
|
||||||
@ -82,17 +81,17 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(window.location.hash.includes('tc.mode=fixed')).toBe(false);
|
expect(window.location.hash.includes('tc.mode=fixed')).toBe(false);
|
||||||
});
|
});
|
||||||
describe("when set in the url", () => {
|
describe("when set in the url", () => {
|
||||||
it("will change from fixed to realtime mode when the mode changes", () => {
|
it("will change from fixed to realtime mode when the mode changes", (done) => {
|
||||||
expectLocationToBeInFixedMode();
|
expectLocationToBeInFixedMode();
|
||||||
|
|
||||||
return switchToRealtimeMode().then(() => {
|
return switchToRealtimeMode().then(() => {
|
||||||
let clock = openmct.time.clock();
|
let clock = openmct.time.clock();
|
||||||
|
|
||||||
expect(clock).toBeDefined();
|
expect(clock).toBeDefined();
|
||||||
expect(clock.key).toBe('local');
|
expect(clock.key).toBe('local');
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("the clock is correctly set in the API from the URL parameters", () => {
|
it("the clock is correctly set in the API from the URL parameters", (done) => {
|
||||||
return switchToRealtimeMode().then(() => {
|
return switchToRealtimeMode().then(() => {
|
||||||
let resolveFunction;
|
let resolveFunction;
|
||||||
|
|
||||||
@ -110,10 +109,11 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(clock).toBeDefined();
|
expect(clock).toBeDefined();
|
||||||
expect(clock.key).toBe('test-clock');
|
expect(clock.key).toBe('test-clock');
|
||||||
openmct.time.off('clock', resolveFunction);
|
openmct.time.off('clock', resolveFunction);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("the clock offsets are correctly set in the API from the URL parameters", () => {
|
it("the clock offsets are correctly set in the API from the URL parameters", (done) => {
|
||||||
return switchToRealtimeMode().then(() => {
|
return switchToRealtimeMode().then(() => {
|
||||||
let resolveFunction;
|
let resolveFunction;
|
||||||
|
|
||||||
@ -132,10 +132,11 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(clockOffsets.start).toBe(-2000);
|
expect(clockOffsets.start).toBe(-2000);
|
||||||
expect(clockOffsets.end).toBe(200);
|
expect(clockOffsets.end).toBe(200);
|
||||||
openmct.time.off('clockOffsets', resolveFunction);
|
openmct.time.off('clockOffsets', resolveFunction);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("the time system is correctly set in the API from the URL parameters", () => {
|
it("the time system is correctly set in the API from the URL parameters", (done) => {
|
||||||
return switchToRealtimeMode().then(() => {
|
return switchToRealtimeMode().then(() => {
|
||||||
let resolveFunction;
|
let resolveFunction;
|
||||||
|
|
||||||
@ -153,6 +154,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(timeSystem).toBeDefined();
|
expect(timeSystem).toBeDefined();
|
||||||
expect(timeSystem.key).toBe('local');
|
expect(timeSystem.key).toBe('local');
|
||||||
openmct.time.off('timeSystem', resolveFunction);
|
openmct.time.off('timeSystem', resolveFunction);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -200,7 +202,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(window.location.hash.includes('tc.timeSystem=utc')).toBe(false);
|
expect(window.location.hash.includes('tc.timeSystem=utc')).toBe(false);
|
||||||
});
|
});
|
||||||
describe("when set in the url", () => {
|
describe("when set in the url", () => {
|
||||||
it("time system changes are reflected in the API", () => {
|
it("time system changes are reflected in the API", (done) => {
|
||||||
let resolveFunction;
|
let resolveFunction;
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@ -216,9 +218,10 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(timeSystem.key).toBe('local');
|
expect(timeSystem.key).toBe('local');
|
||||||
|
|
||||||
openmct.time.off('timeSystem', resolveFunction);
|
openmct.time.off('timeSystem', resolveFunction);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("mode can be changed from realtime to fixed", () => {
|
it("mode can be changed from realtime to fixed", (done) => {
|
||||||
return switchToRealtimeMode().then(() => {
|
return switchToRealtimeMode().then(() => {
|
||||||
expectLocationToBeInRealtimeMode();
|
expectLocationToBeInRealtimeMode();
|
||||||
|
|
||||||
@ -226,9 +229,10 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
}).then(switchToFixedMode).then(() => {
|
}).then(switchToFixedMode).then(() => {
|
||||||
let clock = openmct.time.clock();
|
let clock = openmct.time.clock();
|
||||||
expect(clock).not.toBeDefined();
|
expect(clock).not.toBeDefined();
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("bounds are correctly set in the API from the URL parameters", () => {
|
it("bounds are correctly set in the API from the URL parameters", (done) => {
|
||||||
let resolveFunction;
|
let resolveFunction;
|
||||||
|
|
||||||
expectLocationToBeInFixedMode();
|
expectLocationToBeInFixedMode();
|
||||||
@ -246,9 +250,10 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(bounds).toBeDefined();
|
expect(bounds).toBeDefined();
|
||||||
expect(bounds.start).toBe(222);
|
expect(bounds.start).toBe(222);
|
||||||
expect(bounds.end).toBe(333);
|
expect(bounds.end).toBe(333);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("bounds are correctly set in the API from the URL parameters where only the end bound changes", () => {
|
it("bounds are correctly set in the API from the URL parameters where only the end bound changes", (done) => {
|
||||||
let resolveFunction;
|
let resolveFunction;
|
||||||
|
|
||||||
expectLocationToBeInFixedMode();
|
expectLocationToBeInFixedMode();
|
||||||
@ -265,6 +270,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
|||||||
expect(bounds).toBeDefined();
|
expect(bounds).toBeDefined();
|
||||||
expect(bounds.start).toBe(0);
|
expect(bounds.start).toBe(0);
|
||||||
expect(bounds.end).toBe(333);
|
expect(bounds.end).toBe(333);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -27,7 +27,7 @@ define([
|
|||||||
'zepto',
|
'zepto',
|
||||||
'./dom-observer'
|
'./dom-observer'
|
||||||
], function (AutoflowTabularPlugin, AutoflowTabularConstants, MCT, $, DOMObserver) {
|
], function (AutoflowTabularPlugin, AutoflowTabularConstants, MCT, $, DOMObserver) {
|
||||||
xdescribe("AutoflowTabularPlugin", function () {
|
describe("AutoflowTabularPlugin", function () {
|
||||||
var testType;
|
var testType;
|
||||||
var testObject;
|
var testObject;
|
||||||
var mockmct;
|
var mockmct;
|
||||||
|
@ -36,10 +36,6 @@ describe('the plugin', function () {
|
|||||||
let openmct;
|
let openmct;
|
||||||
let testTelemetryObject;
|
let testTelemetryObject;
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
resetApplicationState(openmct);
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach((done) => {
|
beforeEach((done) => {
|
||||||
testTelemetryObject = {
|
testTelemetryObject = {
|
||||||
identifier: {
|
identifier: {
|
||||||
@ -98,7 +94,7 @@ describe('the plugin', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
resetApplicationState(openmct);
|
return resetApplicationState(openmct);
|
||||||
});
|
});
|
||||||
|
|
||||||
let mockConditionSetObject = {
|
let mockConditionSetObject = {
|
||||||
@ -422,7 +418,7 @@ describe('the plugin', function () {
|
|||||||
"telemetry": "any",
|
"telemetry": "any",
|
||||||
"operation": "isStale",
|
"operation": "isStale",
|
||||||
"input": [
|
"input": [
|
||||||
"1"
|
"0.2"
|
||||||
],
|
],
|
||||||
"metadata": "dataReceived"
|
"metadata": "dataReceived"
|
||||||
}
|
}
|
||||||
@ -462,7 +458,7 @@ describe('the plugin', function () {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should evaluate as stale when telemetry is not received in the allotted time', (done) => {
|
xit('should evaluate as stale when telemetry is not received in the allotted time', (done) => {
|
||||||
|
|
||||||
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||||
@ -481,12 +477,12 @@ describe('the plugin', function () {
|
|||||||
utc: undefined
|
utc: undefined
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
}, 1500);
|
}, 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not evaluate as stale when telemetry is received in the allotted time', (done) => {
|
xit('should not evaluate as stale when telemetry is received in the allotted time', (done) => {
|
||||||
const date = Date.now();
|
const date = Date.now();
|
||||||
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["2"];
|
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["0.4"];
|
||||||
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||||
conditionMgr.telemetryObjects = {
|
conditionMgr.telemetryObjects = {
|
||||||
@ -507,7 +503,7 @@ describe('the plugin', function () {
|
|||||||
utc: undefined
|
utc: undefined
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
}, 1500);
|
}, 300);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -134,6 +134,14 @@ define(['lodash'], function (_) {
|
|||||||
return `configuration.items[${selectionPath[0].context.index}]`;
|
return `configuration.items[${selectionPath[0].context.index}]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAllOfType(selection, specificType) {
|
||||||
|
return selection.filter(selectionPath => {
|
||||||
|
let type = selectionPath[0].context.layoutItem.type;
|
||||||
|
|
||||||
|
return type === specificType;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getAllTypes(selection) {
|
function getAllTypes(selection) {
|
||||||
return selection.filter(selectionPath => {
|
return selection.filter(selectionPath => {
|
||||||
let type = selectionPath[0].context.layoutItem.type;
|
let type = selectionPath[0].context.layoutItem.type;
|
||||||
@ -510,6 +518,54 @@ define(['lodash'], function (_) {
|
|||||||
return allTelemetry;
|
return allTelemetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getToggleUnitsButton(selectedParent, selection) {
|
||||||
|
let applicableItems = getAllOfType(selection, 'telemetry-view');
|
||||||
|
applicableItems = unitsOnly(applicableItems);
|
||||||
|
if (!applicableItems.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
control: "toggle-button",
|
||||||
|
domainObject: selectedParent,
|
||||||
|
applicableSelectedItems: applicableItems,
|
||||||
|
property: function (selectionPath) {
|
||||||
|
return getPath(selectionPath) + '.showUnits';
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: true,
|
||||||
|
icon: 'icon-eye-open',
|
||||||
|
title: "Show units"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: false,
|
||||||
|
icon: 'icon-eye-disabled',
|
||||||
|
title: "Hide units"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function unitsOnly(items) {
|
||||||
|
let results = items.filter((item) => {
|
||||||
|
let currentItem = item[0];
|
||||||
|
let metadata = openmct.telemetry.getMetadata(currentItem.context.item);
|
||||||
|
if (!metadata) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasUnits = metadata
|
||||||
|
.valueMetadatas
|
||||||
|
.filter((metadatum) => metadatum.unit)
|
||||||
|
.length;
|
||||||
|
|
||||||
|
return hasUnits > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
function getViewSwitcherMenu(selectedParent, selectionPath, selection) {
|
function getViewSwitcherMenu(selectedParent, selectionPath, selection) {
|
||||||
if (selection.length === 1) {
|
if (selection.length === 1) {
|
||||||
let displayLayoutContext = selectionPath[1].context,
|
let displayLayoutContext = selectionPath[1].context,
|
||||||
@ -594,6 +650,7 @@ define(['lodash'], function (_) {
|
|||||||
'text-style': [],
|
'text-style': [],
|
||||||
'position': [],
|
'position': [],
|
||||||
'duplicate': [],
|
'duplicate': [],
|
||||||
|
'unit-toggle': [],
|
||||||
'remove': []
|
'remove': []
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -663,6 +720,13 @@ define(['lodash'], function (_) {
|
|||||||
if (toolbar.viewSwitcher.length === 0) {
|
if (toolbar.viewSwitcher.length === 0) {
|
||||||
toolbar.viewSwitcher = [getViewSwitcherMenu(selectedParent, selectionPath, selectedObjects)];
|
toolbar.viewSwitcher = [getViewSwitcherMenu(selectedParent, selectionPath, selectedObjects)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toolbar['unit-toggle'].length === 0) {
|
||||||
|
let toggleUnitsButton = getToggleUnitsButton(selectedParent, selectedObjects);
|
||||||
|
if (toggleUnitsButton) {
|
||||||
|
toolbar['unit-toggle'] = [toggleUnitsButton];
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (layoutItem.type === 'text-view') {
|
} else if (layoutItem.type === 'text-view') {
|
||||||
if (toolbar['text-style'].length === 0) {
|
if (toolbar['text-style'].length === 0) {
|
||||||
toolbar['text-style'] = [
|
toolbar['text-style'] = [
|
||||||
|
@ -58,6 +58,12 @@
|
|||||||
>
|
>
|
||||||
<div class="c-telemetry-view__value-text">
|
<div class="c-telemetry-view__value-text">
|
||||||
{{ telemetryValue }}
|
{{ telemetryValue }}
|
||||||
|
<span
|
||||||
|
v-if="unit && item.showUnits"
|
||||||
|
class="c-telemetry-view__value-text__unit"
|
||||||
|
>
|
||||||
|
{{ unit }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -137,6 +143,12 @@ export default {
|
|||||||
|
|
||||||
return displayMode === 'all' || displayMode === 'value';
|
return displayMode === 'all' || displayMode === 'value';
|
||||||
},
|
},
|
||||||
|
unit() {
|
||||||
|
let value = this.item.value,
|
||||||
|
unit = this.metadata.value(value).unit;
|
||||||
|
|
||||||
|
return unit;
|
||||||
|
},
|
||||||
styleObject() {
|
styleObject() {
|
||||||
return Object.assign({}, {
|
return Object.assign({}, {
|
||||||
fontSize: this.item.size
|
fontSize: this.item.size
|
||||||
@ -257,7 +269,9 @@ export default {
|
|||||||
item: domainObject,
|
item: domainObject,
|
||||||
layoutItem: this.item,
|
layoutItem: this.item,
|
||||||
index: this.index,
|
index: this.index,
|
||||||
updateTelemetryFormat: this.updateTelemetryFormat
|
updateTelemetryFormat: this.updateTelemetryFormat,
|
||||||
|
toggleUnits: this.toggleUnits,
|
||||||
|
showUnits: this.showUnits
|
||||||
};
|
};
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
this.$el, this.context, this.immediatelySelect || this.initSelect);
|
this.$el, this.context, this.immediatelySelect || this.initSelect);
|
||||||
|
346
src/plugins/displayLayout/pluginSpec.js
Normal file
346
src/plugins/displayLayout/pluginSpec.js
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2020, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* 'License'); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||||
|
import DisplayLayoutPlugin from './plugin';
|
||||||
|
|
||||||
|
describe('the plugin', function () {
|
||||||
|
let element;
|
||||||
|
let child;
|
||||||
|
let openmct;
|
||||||
|
let displayLayoutDefinition;
|
||||||
|
|
||||||
|
beforeEach((done) => {
|
||||||
|
openmct = createOpenMct();
|
||||||
|
openmct.install(new DisplayLayoutPlugin({
|
||||||
|
showAsView: []
|
||||||
|
}));
|
||||||
|
displayLayoutDefinition = openmct.types.get('layout');
|
||||||
|
|
||||||
|
element = document.createElement('div');
|
||||||
|
child = document.createElement('div');
|
||||||
|
element.appendChild(child);
|
||||||
|
|
||||||
|
openmct.on('start', done);
|
||||||
|
openmct.startHeadless();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
return resetApplicationState(openmct);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('defines a display layout object type with the correct key', () => {
|
||||||
|
expect(displayLayoutDefinition.definition.name).toEqual('Display Layout');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('provides a view', () => {
|
||||||
|
const testViewObject = {
|
||||||
|
id: 'test-object',
|
||||||
|
type: 'layout',
|
||||||
|
configuration: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||||
|
},
|
||||||
|
'x': 8,
|
||||||
|
'y': 3,
|
||||||
|
'width': 10,
|
||||||
|
'height': 5,
|
||||||
|
'displayMode': 'all',
|
||||||
|
'value': 'sin',
|
||||||
|
'stroke': '',
|
||||||
|
'fill': '',
|
||||||
|
'color': '',
|
||||||
|
'size': '13px',
|
||||||
|
'type': 'telemetry-view',
|
||||||
|
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
layoutGrid: [10, 10]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const applicableViews = openmct.objectViews.get(testViewObject);
|
||||||
|
let displayLayoutViewProvider = applicableViews.find((viewProvider) => viewProvider.key === 'layout.view');
|
||||||
|
expect(displayLayoutViewProvider).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('the alpha numeric format view', () => {
|
||||||
|
let displayLayoutItem;
|
||||||
|
let telemetryItem;
|
||||||
|
let selection;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
displayLayoutItem = {
|
||||||
|
'composition': [
|
||||||
|
],
|
||||||
|
'configuration': {
|
||||||
|
'items': [
|
||||||
|
{
|
||||||
|
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||||
|
},
|
||||||
|
'x': 8,
|
||||||
|
'y': 3,
|
||||||
|
'width': 10,
|
||||||
|
'height': 5,
|
||||||
|
'displayMode': 'all',
|
||||||
|
'value': 'sin',
|
||||||
|
'stroke': '',
|
||||||
|
'fill': '',
|
||||||
|
'color': '',
|
||||||
|
'size': '13px',
|
||||||
|
'type': 'telemetry-view',
|
||||||
|
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'layoutGrid': [
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'name': 'Display Layout',
|
||||||
|
'type': 'layout',
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': 'c5e636c1-6771-4c9c-b933-8665cab189b3'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
telemetryItem = {
|
||||||
|
'telemetry': {
|
||||||
|
'period': 5,
|
||||||
|
'amplitude': 5,
|
||||||
|
'offset': 5,
|
||||||
|
'dataRateInHz': 5,
|
||||||
|
'phase': 5,
|
||||||
|
'randomness': 0
|
||||||
|
},
|
||||||
|
'name': 'Sine Wave Generator',
|
||||||
|
'type': 'generator',
|
||||||
|
'modified': 1592851063871,
|
||||||
|
'location': 'mine',
|
||||||
|
'persisted': 1592851063871,
|
||||||
|
'id': '55122607-e65e-44d5-9c9d-9c31a914ca89',
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
selection = [
|
||||||
|
[{
|
||||||
|
context: {
|
||||||
|
'layoutItem': displayLayoutItem.configuration.items[0],
|
||||||
|
'item': telemetryItem,
|
||||||
|
'index': 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
'item': displayLayoutItem,
|
||||||
|
'supportsMultiSelect': true
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('provides an alphanumeric format view', () => {
|
||||||
|
const displayLayoutAlphaNumFormatView = openmct.inspectorViews.get(selection);
|
||||||
|
expect(displayLayoutAlphaNumFormatView.length).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('the toolbar', () => {
|
||||||
|
let displayLayoutItem;
|
||||||
|
let selection;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
displayLayoutItem = {
|
||||||
|
'composition': [
|
||||||
|
],
|
||||||
|
'configuration': {
|
||||||
|
'items': [
|
||||||
|
{
|
||||||
|
'fill': '#717171',
|
||||||
|
'stroke': '',
|
||||||
|
'x': 1,
|
||||||
|
'y': 1,
|
||||||
|
'width': 10,
|
||||||
|
'height': 5,
|
||||||
|
'type': 'box-view',
|
||||||
|
'id': '89b88746-d325-487b-aec4-11b79afff9e8'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'x': 18,
|
||||||
|
'y': 9,
|
||||||
|
'x2': 23,
|
||||||
|
'y2': 4,
|
||||||
|
'stroke': '#717171',
|
||||||
|
'type': 'line-view',
|
||||||
|
'id': '57d49a28-7863-43bd-9593-6570758916f0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||||
|
},
|
||||||
|
'x': 8,
|
||||||
|
'y': 3,
|
||||||
|
'width': 10,
|
||||||
|
'height': 5,
|
||||||
|
'displayMode': 'all',
|
||||||
|
'value': 'sin',
|
||||||
|
'stroke': '',
|
||||||
|
'fill': '',
|
||||||
|
'color': '',
|
||||||
|
'size': '13px',
|
||||||
|
'type': 'telemetry-view',
|
||||||
|
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
'width': 32,
|
||||||
|
'height': 18,
|
||||||
|
'x': 78,
|
||||||
|
'y': 8,
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
|
||||||
|
},
|
||||||
|
'hasFrame': true,
|
||||||
|
'type': 'subobject-view',
|
||||||
|
'id': 'c0ff485a-344c-4e70-8d83-a9d9998a69fc'
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'layoutGrid': [
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'name': 'Display Layout',
|
||||||
|
'type': 'layout',
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': 'c5e636c1-6771-4c9c-b933-8665cab189b3'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
selection = [
|
||||||
|
[{
|
||||||
|
context: {
|
||||||
|
'layoutItem': displayLayoutItem.configuration.items[1],
|
||||||
|
'index': 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
'item': displayLayoutItem,
|
||||||
|
'supportsMultiSelect': true
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
context: {
|
||||||
|
'layoutItem': displayLayoutItem.configuration.items[0],
|
||||||
|
'index': 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
item: displayLayoutItem,
|
||||||
|
'supportsMultiSelect': true
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
context: {
|
||||||
|
'layoutItem': displayLayoutItem.configuration.items[2],
|
||||||
|
'item': displayLayoutItem.configuration.items[2],
|
||||||
|
'index': 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
item: displayLayoutItem,
|
||||||
|
'supportsMultiSelect': true
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
context: {
|
||||||
|
'item': {
|
||||||
|
|
||||||
|
'composition': [
|
||||||
|
{
|
||||||
|
'namespace': '',
|
||||||
|
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'configuration': {
|
||||||
|
'series': [
|
||||||
|
{
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'yAxis': {
|
||||||
|
},
|
||||||
|
'xAxis': {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'name': 'Unnamed Overlay Plot',
|
||||||
|
'type': 'telemetry.plot.overlay',
|
||||||
|
'modified': 1594142141929,
|
||||||
|
'location': 'mine',
|
||||||
|
'identifier': {
|
||||||
|
'namespace': '',
|
||||||
|
'key': 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
|
||||||
|
},
|
||||||
|
'persisted': 1594142141929
|
||||||
|
|
||||||
|
},
|
||||||
|
'layoutItem': displayLayoutItem.configuration.items[3],
|
||||||
|
'index': 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
item: displayLayoutItem,
|
||||||
|
'supportsMultiSelect': true
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('provides controls including separators', () => {
|
||||||
|
const displayLayoutToolbar = openmct.toolbars.get(selection);
|
||||||
|
expect(displayLayoutToolbar.length).toBe(9);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -46,7 +46,7 @@ describe("the plugin", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
resetApplicationState(openmct);
|
return resetApplicationState(openmct);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('installs the new folder action', () => {
|
it('installs the new folder action', () => {
|
||||||
|
@ -35,10 +35,6 @@ describe('the plugin', () => {
|
|||||||
parentElement,
|
parentElement,
|
||||||
mockMessages = ['error', 'test', 'notifications'];
|
mockMessages = ['error', 'test', 'notifications'];
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
resetApplicationState();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach((done) => {
|
beforeEach((done) => {
|
||||||
openmct = createOpenMct();
|
openmct = createOpenMct();
|
||||||
|
|
||||||
@ -61,7 +57,7 @@ describe('the plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
resetApplicationState(openmct);
|
return resetApplicationState(openmct);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('the indicator plugin element', () => {
|
describe('the indicator plugin element', () => {
|
||||||
|
53
src/plugins/persistence/couch/CouchDocument.js
Normal file
53
src/plugins/persistence/couch/CouchDocument.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A CouchDocument describes domain object model in a format
|
||||||
|
* which is easily read-written to CouchDB. This includes
|
||||||
|
* Couch's _id and _rev fields, as well as a separate
|
||||||
|
* metadata field which contains a subset of information found
|
||||||
|
* in the model itself (to support search optimization with
|
||||||
|
* CouchDB views.)
|
||||||
|
* @memberof platform/persistence/couch
|
||||||
|
* @constructor
|
||||||
|
* @param {string} id the id under which to store this mode
|
||||||
|
* @param {object} model the model to store
|
||||||
|
* @param {string} rev the revision to include (or undefined,
|
||||||
|
* if no revision should be noted for couch)
|
||||||
|
* @param {boolean} whether or not to mark this document as
|
||||||
|
* deleted (see CouchDB docs for _deleted)
|
||||||
|
*/
|
||||||
|
export default function CouchDocument(id, model, rev, markDeleted) {
|
||||||
|
return {
|
||||||
|
"_id": id,
|
||||||
|
"_rev": rev,
|
||||||
|
"_deleted": markDeleted,
|
||||||
|
"metadata": {
|
||||||
|
"category": "domain object",
|
||||||
|
"type": model.type,
|
||||||
|
"owner": "admin",
|
||||||
|
"name": model.name,
|
||||||
|
"created": Date.now()
|
||||||
|
},
|
||||||
|
"model": model
|
||||||
|
};
|
||||||
|
}
|
134
src/plugins/persistence/couch/CouchObjectProvider.js
Normal file
134
src/plugins/persistence/couch/CouchObjectProvider.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import CouchDocument from "./CouchDocument";
|
||||||
|
import CouchObjectQueue from "./CouchObjectQueue";
|
||||||
|
|
||||||
|
const REV = "_rev";
|
||||||
|
const ID = "_id";
|
||||||
|
|
||||||
|
export default class CouchObjectProvider {
|
||||||
|
constructor(openmct, url, namespace) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
this.url = url;
|
||||||
|
this.namespace = namespace;
|
||||||
|
this.objectQueue = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
request(subPath, method, value) {
|
||||||
|
return fetch(this.url + '/' + subPath, {
|
||||||
|
method: method,
|
||||||
|
body: JSON.stringify(value)
|
||||||
|
}).then(response => response.json())
|
||||||
|
.then(function (response) {
|
||||||
|
return response;
|
||||||
|
}, function () {
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the response to a create/update/delete request;
|
||||||
|
// track the rev if it's valid, otherwise return false to
|
||||||
|
// indicate that the request failed.
|
||||||
|
// persist any queued objects
|
||||||
|
checkResponse(response, intermediateResponse) {
|
||||||
|
let requestSuccess = false;
|
||||||
|
const id = response.id;
|
||||||
|
let rev;
|
||||||
|
if (response && response.ok) {
|
||||||
|
rev = response.rev;
|
||||||
|
requestSuccess = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
intermediateResponse.resolve(requestSuccess);
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
if (!this.objectQueue[id]) {
|
||||||
|
this.objectQueue[id] = new CouchObjectQueue(undefined, rev);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.objectQueue[id].updateRevision(rev);
|
||||||
|
this.objectQueue[id].pending = false;
|
||||||
|
if (this.objectQueue[id].hasNext()) {
|
||||||
|
this.updateQueued(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getModel(response) {
|
||||||
|
if (response && response.model) {
|
||||||
|
let key = response[ID];
|
||||||
|
let object = response.model;
|
||||||
|
object.identifier = {
|
||||||
|
namespace: this.namespace,
|
||||||
|
key: key
|
||||||
|
};
|
||||||
|
if (!this.objectQueue[key]) {
|
||||||
|
this.objectQueue[key] = new CouchObjectQueue(undefined, response[REV]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.objectQueue[key].updateRevision(response[REV]);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get(identifier) {
|
||||||
|
return this.request(identifier.key, "GET").then(this.getModel.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
getIntermediateResponse() {
|
||||||
|
let intermediateResponse = {};
|
||||||
|
intermediateResponse.promise = new Promise(function (resolve, reject) {
|
||||||
|
intermediateResponse.resolve = resolve;
|
||||||
|
intermediateResponse.reject = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
return intermediateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
enqueueObject(key, model, intermediateResponse) {
|
||||||
|
if (this.objectQueue[key]) {
|
||||||
|
this.objectQueue[key].enqueue({
|
||||||
|
model,
|
||||||
|
intermediateResponse
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.objectQueue[key] = new CouchObjectQueue({
|
||||||
|
model,
|
||||||
|
intermediateResponse
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create(model) {
|
||||||
|
let intermediateResponse = this.getIntermediateResponse();
|
||||||
|
const key = model.identifier.key;
|
||||||
|
this.enqueueObject(key, model, intermediateResponse);
|
||||||
|
this.objectQueue[key].pending = true;
|
||||||
|
const queued = this.objectQueue[key].dequeue();
|
||||||
|
this.request(key, "PUT", new CouchDocument(key, queued.model)).then((response) => {
|
||||||
|
this.checkResponse(response, queued.intermediateResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
return intermediateResponse.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateQueued(key) {
|
||||||
|
if (!this.objectQueue[key].pending) {
|
||||||
|
this.objectQueue[key].pending = true;
|
||||||
|
const queued = this.objectQueue[key].dequeue();
|
||||||
|
this.request(key, "PUT", new CouchDocument(key, queued.model, this.objectQueue[key].rev)).then((response) => {
|
||||||
|
this.checkResponse(response, queued.intermediateResponse);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update(model) {
|
||||||
|
let intermediateResponse = this.getIntermediateResponse();
|
||||||
|
const key = model.identifier.key;
|
||||||
|
this.enqueueObject(key, model, intermediateResponse);
|
||||||
|
this.updateQueued(key);
|
||||||
|
|
||||||
|
return intermediateResponse.promise;
|
||||||
|
}
|
||||||
|
}
|
32
src/plugins/persistence/couch/CouchObjectQueue.js
Normal file
32
src/plugins/persistence/couch/CouchObjectQueue.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//TODO: should we limit the queue size?
|
||||||
|
//const MAX_QUEUE_SIZE = 10;
|
||||||
|
|
||||||
|
export default class CouchObjectQueue {
|
||||||
|
constructor(object, rev) {
|
||||||
|
this.rev = rev;
|
||||||
|
this.objects = object ? [object] : [];
|
||||||
|
this.pending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRevision(rev) {
|
||||||
|
this.rev = rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasNext() {
|
||||||
|
return this.objects.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
enqueue(item) {
|
||||||
|
this.objects.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
dequeue() {
|
||||||
|
return this.objects.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.rev = undefined;
|
||||||
|
this.objects = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
src/plugins/persistence/couch/plugin.js
Normal file
8
src/plugins/persistence/couch/plugin.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import CouchObjectProvider from './CouchObjectProvider';
|
||||||
|
const NAMESPACE = '';
|
||||||
|
|
||||||
|
export default function CouchPlugin(url) {
|
||||||
|
return function install(openmct) {
|
||||||
|
openmct.objects.addProvider(NAMESPACE, new CouchObjectProvider(openmct, url, NAMESPACE));
|
||||||
|
};
|
||||||
|
}
|
102
src/plugins/persistence/couch/pluginSpec.js
Normal file
102
src/plugins/persistence/couch/pluginSpec.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2020, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
import CouchPlugin from './plugin.js';
|
||||||
|
import {
|
||||||
|
createOpenMct,
|
||||||
|
resetApplicationState
|
||||||
|
} from 'utils/testing';
|
||||||
|
import CouchObjectProvider from "@/plugins/persistence/couch/CouchObjectProvider";
|
||||||
|
import CouchObjectQueue from "@/plugins/persistence/couch/CouchObjectQueue";
|
||||||
|
|
||||||
|
describe("the plugin", () => {
|
||||||
|
let openmct;
|
||||||
|
let element;
|
||||||
|
let child;
|
||||||
|
let provider;
|
||||||
|
let testSpace = "testSpace";
|
||||||
|
let testPath = "/test/db";
|
||||||
|
let mockDomainObject = {
|
||||||
|
identifier: {
|
||||||
|
namespace: '',
|
||||||
|
key: "some-value"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach((done) => {
|
||||||
|
openmct = createOpenMct(false);
|
||||||
|
openmct.install(new CouchPlugin(testSpace, testPath));
|
||||||
|
|
||||||
|
element = document.createElement('div');
|
||||||
|
child = document.createElement('div');
|
||||||
|
element.appendChild(child);
|
||||||
|
|
||||||
|
openmct.on('start', done);
|
||||||
|
openmct.startHeadless();
|
||||||
|
|
||||||
|
provider = openmct.objects.getProvider(mockDomainObject.identifier);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('registers a provider for objects', () => {
|
||||||
|
expect(provider).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gets an object', () => {
|
||||||
|
openmct.objects.get(mockDomainObject.identifier).then((result) => {
|
||||||
|
expect(provider.get).toHaveBeenCalled();
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an object', () => {
|
||||||
|
openmct.objects.save(mockDomainObject).then((result) => {
|
||||||
|
expect(provider.create).toHaveBeenCalled();
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates an object', () => {
|
||||||
|
openmct.objects.save(mockDomainObject).then((result) => {
|
||||||
|
expect(provider.create).toHaveBeenCalled();
|
||||||
|
openmct.objects.save(mockDomainObject).then((updatedResult) => {
|
||||||
|
expect(provider.update).toHaveBeenCalled();
|
||||||
|
expect(updatedResult).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates queued objects', () => {
|
||||||
|
let couchProvider = new CouchObjectProvider(openmct, 'http://localhost', '');
|
||||||
|
let intermediateResponse = couchProvider.getIntermediateResponse();
|
||||||
|
spyOn(couchProvider, 'updateQueued');
|
||||||
|
couchProvider.enqueueObject(mockDomainObject.identifier.key, mockDomainObject, intermediateResponse);
|
||||||
|
couchProvider.objectQueue[mockDomainObject.identifier.key].updateRevision(1);
|
||||||
|
couchProvider.update(mockDomainObject);
|
||||||
|
expect(couchProvider.objectQueue[mockDomainObject.identifier.key].hasNext()).toBe(2);
|
||||||
|
couchProvider.checkResponse({
|
||||||
|
ok: true,
|
||||||
|
rev: 2,
|
||||||
|
id: mockDomainObject.identifier.key
|
||||||
|
}, intermediateResponse);
|
||||||
|
|
||||||
|
expect(couchProvider.updateQueued).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
});
|
@ -49,7 +49,7 @@
|
|||||||
ng-style="{ 'background-color': series.get('color').asHexString() }">
|
ng-style="{ 'background-color': series.get('color').asHexString() }">
|
||||||
</span>
|
</span>
|
||||||
<span class="is-missing__indicator" title="This item is missing"></span>
|
<span class="is-missing__indicator" title="This item is missing"></span>
|
||||||
<span class="plot-series-name">{{ series.get('name') }}</span>
|
<span class="plot-series-name">{{ series.nameWithUnit() }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="plot-series-value hover-value-enabled value-to-display-{{ legend.get('valueToShowWhenCollapsed') }} {{ series.closest.mctLimitState.cssClass }}"
|
<div class="plot-series-value hover-value-enabled value-to-display-{{ legend.get('valueToShowWhenCollapsed') }} {{ series.closest.mctLimitState.cssClass }}"
|
||||||
ng-class="{ 'cursor-hover': (legend.get('valueToShowWhenCollapsed').indexOf('nearest') != -1) }"
|
ng-class="{ 'cursor-hover': (legend.get('valueToShowWhenCollapsed').indexOf('nearest') != -1) }"
|
||||||
@ -79,6 +79,9 @@
|
|||||||
<th ng-if="legend.get('showValueWhenExpanded')">
|
<th ng-if="legend.get('showValueWhenExpanded')">
|
||||||
Value
|
Value
|
||||||
</th>
|
</th>
|
||||||
|
<th ng-if="legend.get('showUnitsWhenExpanded')">
|
||||||
|
Unit
|
||||||
|
</th>
|
||||||
<th ng-if="legend.get('showMinimumWhenExpanded')"
|
<th ng-if="legend.get('showMinimumWhenExpanded')"
|
||||||
class="mobile-hide">
|
class="mobile-hide">
|
||||||
Min
|
Min
|
||||||
@ -114,6 +117,11 @@
|
|||||||
{{ series.formatY(series.closest) }}
|
{{ series.formatY(series.closest) }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td ng-if="legend.get('showUnitsWhenExpanded')">
|
||||||
|
<span class="plot-series-value cursor-hover hover-value-enabled">
|
||||||
|
{{ series.get('unit') }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
<td ng-if="legend.get('showMinimumWhenExpanded')"
|
<td ng-if="legend.get('showMinimumWhenExpanded')"
|
||||||
class="mobile-hide">
|
class="mobile-hide">
|
||||||
<span class="plot-series-value">
|
<span class="plot-series-value">
|
||||||
|
@ -140,6 +140,7 @@
|
|||||||
<span ng-if="config.legend.get('showValueWhenExpanded')">Value</span>
|
<span ng-if="config.legend.get('showValueWhenExpanded')">Value</span>
|
||||||
<span ng-if="config.legend.get('showMinimumWhenExpanded')">Min</span>
|
<span ng-if="config.legend.get('showMinimumWhenExpanded')">Min</span>
|
||||||
<span ng-if="config.legend.get('showMaximumWhenExpanded')">Max</span>
|
<span ng-if="config.legend.get('showMaximumWhenExpanded')">Max</span>
|
||||||
|
<span ng-if="config.legend.get('showUnitsWhenExpanded')">Units</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -201,6 +201,7 @@
|
|||||||
<option value="nearestValue">Nearest value</option>
|
<option value="nearestValue">Nearest value</option>
|
||||||
<option value="min">Minimum value</option>
|
<option value="min">Minimum value</option>
|
||||||
<option value="max">Maximum value</option>
|
<option value="max">Maximum value</option>
|
||||||
|
<option value="units">showUnitsWhenExpanded</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -217,6 +218,8 @@
|
|||||||
ng-model="form.showMinimumWhenExpanded"/> Minimum value</li>
|
ng-model="form.showMinimumWhenExpanded"/> Minimum value</li>
|
||||||
<li><input type="checkbox"
|
<li><input type="checkbox"
|
||||||
ng-model="form.showMaximumWhenExpanded"/> Maximum value</li>
|
ng-model="form.showMaximumWhenExpanded"/> Maximum value</li>
|
||||||
|
<li><input type="checkbox"
|
||||||
|
ng-model="form.showUnitsWhenExpanded"/> Units</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,7 +53,8 @@ define([
|
|||||||
showTimestampWhenExpanded: true,
|
showTimestampWhenExpanded: true,
|
||||||
showValueWhenExpanded: true,
|
showValueWhenExpanded: true,
|
||||||
showMaximumWhenExpanded: true,
|
showMaximumWhenExpanded: true,
|
||||||
showMinimumWhenExpanded: true
|
showMinimumWhenExpanded: true,
|
||||||
|
showUnitsWhenExpanded: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -102,6 +102,7 @@ define([
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
name: options.domainObject.name,
|
name: options.domainObject.name,
|
||||||
|
unit: range.unit,
|
||||||
xKey: options.collection.plot.xAxis.get('key'),
|
xKey: options.collection.plot.xAxis.get('key'),
|
||||||
yKey: range.key,
|
yKey: range.key,
|
||||||
markers: true,
|
markers: true,
|
||||||
@ -439,6 +440,11 @@ define([
|
|||||||
const markerSize = this.get('markerSize');
|
const markerSize = this.get('markerSize');
|
||||||
|
|
||||||
return `${markerShape}: ${markerSize}px`;
|
return `${markerShape}: ${markerSize}px`;
|
||||||
|
},
|
||||||
|
nameWithUnit: function () {
|
||||||
|
let unit = this.get('unit');
|
||||||
|
|
||||||
|
return this.get('name') + (unit ? ' ' + unit : '');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,6 +65,11 @@ define([
|
|||||||
modelProp: 'showMinimumWhenExpanded',
|
modelProp: 'showMinimumWhenExpanded',
|
||||||
coerce: Boolean,
|
coerce: Boolean,
|
||||||
objectPath: 'configuration.legend.showMinimumWhenExpanded'
|
objectPath: 'configuration.legend.showMinimumWhenExpanded'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modelProp: 'showUnitsWhenExpanded',
|
||||||
|
coerce: Boolean,
|
||||||
|
objectPath: 'configuration.legend.showUnitsWhenExpanded'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -54,7 +54,8 @@ define([
|
|||||||
'./themes/snow',
|
'./themes/snow',
|
||||||
'./URLTimeSettingsSynchronizer/plugin',
|
'./URLTimeSettingsSynchronizer/plugin',
|
||||||
'./notificationIndicator/plugin',
|
'./notificationIndicator/plugin',
|
||||||
'./newFolderAction/plugin'
|
'./newFolderAction/plugin',
|
||||||
|
'./persistence/couch/plugin'
|
||||||
], function (
|
], function (
|
||||||
_,
|
_,
|
||||||
UTCTimeSystem,
|
UTCTimeSystem,
|
||||||
@ -89,12 +90,12 @@ define([
|
|||||||
Snow,
|
Snow,
|
||||||
URLTimeSettingsSynchronizer,
|
URLTimeSettingsSynchronizer,
|
||||||
NotificationIndicator,
|
NotificationIndicator,
|
||||||
NewFolderAction
|
NewFolderAction,
|
||||||
|
CouchDBPlugin
|
||||||
) {
|
) {
|
||||||
var bundleMap = {
|
var bundleMap = {
|
||||||
LocalStorage: 'platform/persistence/local',
|
LocalStorage: 'platform/persistence/local',
|
||||||
MyItems: 'platform/features/my-items',
|
MyItems: 'platform/features/my-items',
|
||||||
CouchDB: 'platform/persistence/couch',
|
|
||||||
Elasticsearch: 'platform/persistence/elastic'
|
Elasticsearch: 'platform/persistence/elastic'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,27 +127,7 @@ define([
|
|||||||
|
|
||||||
plugins.Conductor = TimeConductorPlugin.default;
|
plugins.Conductor = TimeConductorPlugin.default;
|
||||||
|
|
||||||
plugins.CouchDB = function (url) {
|
plugins.CouchDB = CouchDBPlugin.default;
|
||||||
return function (openmct) {
|
|
||||||
if (url) {
|
|
||||||
var bundleName = "config/couch";
|
|
||||||
openmct.legacyRegistry.register(bundleName, {
|
|
||||||
"extensions": {
|
|
||||||
"constants": [
|
|
||||||
{
|
|
||||||
"key": "COUCHDB_PATH",
|
|
||||||
"value": url,
|
|
||||||
"priority": "mandatory"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
openmct.legacyRegistry.enable(bundleName);
|
|
||||||
}
|
|
||||||
|
|
||||||
openmct.legacyRegistry.enable(bundleMap.CouchDB);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
plugins.Elasticsearch = function (url) {
|
plugins.Elasticsearch = function (url) {
|
||||||
return function (openmct) {
|
return function (openmct) {
|
||||||
|
@ -27,6 +27,7 @@ define([
|
|||||||
'./collections/FilteredTableRowCollection',
|
'./collections/FilteredTableRowCollection',
|
||||||
'./TelemetryTableRow',
|
'./TelemetryTableRow',
|
||||||
'./TelemetryTableColumn',
|
'./TelemetryTableColumn',
|
||||||
|
'./TelemetryTableUnitColumn',
|
||||||
'./TelemetryTableConfiguration'
|
'./TelemetryTableConfiguration'
|
||||||
], function (
|
], function (
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
@ -35,6 +36,7 @@ define([
|
|||||||
FilteredTableRowCollection,
|
FilteredTableRowCollection,
|
||||||
TelemetryTableRow,
|
TelemetryTableRow,
|
||||||
TelemetryTableColumn,
|
TelemetryTableColumn,
|
||||||
|
TelemetryTableUnitColumn,
|
||||||
TelemetryTableConfiguration
|
TelemetryTableConfiguration
|
||||||
) {
|
) {
|
||||||
class TelemetryTable extends EventEmitter {
|
class TelemetryTable extends EventEmitter {
|
||||||
@ -210,10 +212,14 @@ define([
|
|||||||
|
|
||||||
addColumnsForObject(telemetryObject) {
|
addColumnsForObject(telemetryObject) {
|
||||||
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
||||||
|
|
||||||
metadataValues.forEach(metadatum => {
|
metadataValues.forEach(metadatum => {
|
||||||
let column = this.createColumn(metadatum);
|
let column = this.createColumn(metadatum);
|
||||||
this.configuration.addSingleColumnForObject(telemetryObject, column);
|
this.configuration.addSingleColumnForObject(telemetryObject, column);
|
||||||
|
// add units column if available
|
||||||
|
if (metadatum.unit !== undefined) {
|
||||||
|
let unitColumn = this.createUnitColumn(metadatum);
|
||||||
|
this.configuration.addSingleColumnForObject(telemetryObject, unitColumn);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +227,10 @@ define([
|
|||||||
return new TelemetryTableColumn(this.openmct, metadatum);
|
return new TelemetryTableColumn(this.openmct, metadatum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createUnitColumn(metadatum) {
|
||||||
|
return new TelemetryTableUnitColumn(this.openmct, metadatum);
|
||||||
|
}
|
||||||
|
|
||||||
subscribeTo(telemetryObject) {
|
subscribeTo(telemetryObject) {
|
||||||
let subscribeOptions = this.buildOptionsFromConfiguration(telemetryObject);
|
let subscribeOptions = this.buildOptionsFromConfiguration(telemetryObject);
|
||||||
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||||
|
@ -70,8 +70,10 @@ define([], function () {
|
|||||||
getCellLimitClasses() {
|
getCellLimitClasses() {
|
||||||
if (!this.cellLimitClasses) {
|
if (!this.cellLimitClasses) {
|
||||||
this.cellLimitClasses = Object.values(this.columns).reduce((alarmStateMap, column) => {
|
this.cellLimitClasses = Object.values(this.columns).reduce((alarmStateMap, column) => {
|
||||||
let limitEvaluation = this.limitEvaluator.evaluate(this.datum, column.getMetadatum());
|
if (!column.isUnit) {
|
||||||
alarmStateMap[column.getKey()] = limitEvaluation && limitEvaluation.cssClass;
|
let limitEvaluation = this.limitEvaluator.evaluate(this.datum, column.getMetadatum());
|
||||||
|
alarmStateMap[column.getKey()] = limitEvaluation && limitEvaluation.cssClass;
|
||||||
|
}
|
||||||
|
|
||||||
return alarmStateMap;
|
return alarmStateMap;
|
||||||
}, {});
|
}, {});
|
||||||
|
60
src/plugins/telemetryTable/TelemetryTableUnitColumn.js
Normal file
60
src/plugins/telemetryTable/TelemetryTableUnitColumn.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
define([
|
||||||
|
'./TelemetryTableColumn.js'
|
||||||
|
], function (
|
||||||
|
TelemetryTableColumn
|
||||||
|
) {
|
||||||
|
class TelemetryTableUnitColumn extends TelemetryTableColumn {
|
||||||
|
constructor(openmct, metadatum) {
|
||||||
|
super(openmct, metadatum);
|
||||||
|
this.isUnit = true;
|
||||||
|
this.titleValue += ' Unit';
|
||||||
|
this.formatter = {
|
||||||
|
format: (datum) => {
|
||||||
|
return this.metadatum.unit;
|
||||||
|
},
|
||||||
|
parse: (datum) => {
|
||||||
|
return this.metadatum.unit;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getKey() {
|
||||||
|
return this.metadatum.key + '-unit';
|
||||||
|
}
|
||||||
|
|
||||||
|
getTitle() {
|
||||||
|
return this.metadatum.name + ' Unit';
|
||||||
|
}
|
||||||
|
|
||||||
|
getRawValue(telemetryDatum) {
|
||||||
|
return this.metadatum.unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFormattedValue(telemetryDatum) {
|
||||||
|
return this.formatter.format(telemetryDatum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TelemetryTableUnitColumn;
|
||||||
|
});
|
@ -69,6 +69,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TelemetryTableColumn from '../TelemetryTableColumn';
|
import TelemetryTableColumn from '../TelemetryTableColumn';
|
||||||
|
import TelemetryTableUnitColumn from '../TelemetryTableUnitColumn';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['tableConfiguration', 'openmct'],
|
inject: ['tableConfiguration', 'openmct'],
|
||||||
@ -131,10 +132,14 @@ export default {
|
|||||||
},
|
},
|
||||||
addColumnsForObject(telemetryObject) {
|
addColumnsForObject(telemetryObject) {
|
||||||
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
||||||
|
|
||||||
metadataValues.forEach(metadatum => {
|
metadataValues.forEach(metadatum => {
|
||||||
let column = new TelemetryTableColumn(this.openmct, metadatum);
|
let column = new TelemetryTableColumn(this.openmct, metadatum);
|
||||||
this.tableConfiguration.addSingleColumnForObject(telemetryObject, column);
|
this.tableConfiguration.addSingleColumnForObject(telemetryObject, column);
|
||||||
|
// if units are available, need to add columns to be hidden
|
||||||
|
if (metadatum.unit !== undefined) {
|
||||||
|
let unitColumn = new TelemetryTableUnitColumn(this.openmct, metadatum);
|
||||||
|
this.tableConfiguration.addSingleColumnForObject(telemetryObject, unitColumn);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
toggleHeaderVisibility() {
|
toggleHeaderVisibility() {
|
||||||
|
@ -117,7 +117,7 @@
|
|||||||
title="Deselect All"
|
title="Deselect All"
|
||||||
@click="unmarkAllRows()"
|
@click="unmarkAllRows()"
|
||||||
>
|
>
|
||||||
<span class="c-button__label">Deselect All</span>
|
<span class="c-button__label">{{ `Deselect ${marking.disableMultiSelect ? '' : 'All'}` }} </span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<slot name="buttons"></slot>
|
<slot name="buttons"></slot>
|
||||||
@ -303,6 +303,7 @@ export default {
|
|||||||
default() {
|
default() {
|
||||||
return {
|
return {
|
||||||
enable: false,
|
enable: false,
|
||||||
|
disableMultiSelect: false,
|
||||||
useAlternateControlBar: false,
|
useAlternateControlBar: false,
|
||||||
rowName: '',
|
rowName: '',
|
||||||
rowNamePlural: ""
|
rowNamePlural: ""
|
||||||
@ -787,6 +788,11 @@ export default {
|
|||||||
this.$set(markedRow, 'marked', true);
|
this.$set(markedRow, 'marked', true);
|
||||||
this.pause();
|
this.pause();
|
||||||
|
|
||||||
|
if (this.marking.disableMultiSelect) {
|
||||||
|
this.unmarkAllRows();
|
||||||
|
insertMethod = 'push';
|
||||||
|
}
|
||||||
|
|
||||||
this.markedRows[insertMethod](markedRow);
|
this.markedRows[insertMethod](markedRow);
|
||||||
},
|
},
|
||||||
unmarkAllRows(skipUnpause) {
|
unmarkAllRows(skipUnpause) {
|
||||||
@ -800,7 +806,7 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.markedRows.length) {
|
if (!this.markedRows.length || this.marking.disableMultiSelect) {
|
||||||
this.markRow(rowIndex);
|
this.markRow(rowIndex);
|
||||||
} else {
|
} else {
|
||||||
if (this.markedRows.length > 1) {
|
if (this.markedRows.length > 1) {
|
||||||
|
@ -28,16 +28,27 @@ import {
|
|||||||
resetApplicationState
|
resetApplicationState
|
||||||
} from 'utils/testing';
|
} from 'utils/testing';
|
||||||
|
|
||||||
|
class MockDataTransfer {
|
||||||
|
constructor() {
|
||||||
|
this.data = {};
|
||||||
|
}
|
||||||
|
get types() {
|
||||||
|
return Object.keys(this.data);
|
||||||
|
}
|
||||||
|
setData(format, data) {
|
||||||
|
this.data[format] = data;
|
||||||
|
}
|
||||||
|
getData(format) {
|
||||||
|
return this.data[format];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe("the plugin", () => {
|
describe("the plugin", () => {
|
||||||
let openmct;
|
let openmct;
|
||||||
let tablePlugin;
|
let tablePlugin;
|
||||||
let element;
|
let element;
|
||||||
let child;
|
let child;
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
resetApplicationState();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach((done) => {
|
beforeEach((done) => {
|
||||||
openmct = createOpenMct();
|
openmct = createOpenMct();
|
||||||
|
|
||||||
@ -67,7 +78,7 @@ describe("the plugin", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
resetApplicationState(openmct);
|
return resetApplicationState(openmct);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("defines a table object", function () {
|
describe("defines a table object", function () {
|
||||||
@ -167,7 +178,7 @@ describe("the plugin", () => {
|
|||||||
|
|
||||||
it("Renders a row for every telemetry datum returned", () => {
|
it("Renders a row for every telemetry datum returned", () => {
|
||||||
let rows = element.querySelectorAll('table.c-telemetry-table__body tr');
|
let rows = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||||
expect(rows.length).toBe(3);
|
expect(rows.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Renders a column for every item in telemetry metadata", () => {
|
it("Renders a column for every item in telemetry metadata", () => {
|
||||||
@ -191,7 +202,7 @@ describe("the plugin", () => {
|
|||||||
|
|
||||||
dragStartEvent.dataTransfer =
|
dragStartEvent.dataTransfer =
|
||||||
dragOverEvent.dataTransfer =
|
dragOverEvent.dataTransfer =
|
||||||
dropEvent.dataTransfer = new DataTransfer();
|
dropEvent.dataTransfer = new MockDataTransfer();
|
||||||
|
|
||||||
fromColumn.dispatchEvent(dragStartEvent);
|
fromColumn.dispatchEvent(dragStartEvent);
|
||||||
toColumn.dispatchEvent(dragOverEvent);
|
toColumn.dispatchEvent(dragOverEvent);
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
<ConductorHistory
|
<ConductorHistory
|
||||||
v-if="isFixed"
|
v-if="isFixed"
|
||||||
class="c-conductor__history-select"
|
class="c-conductor__history-select"
|
||||||
:bounds="openmct.time.bounds()"
|
:bounds="bounds"
|
||||||
:time-system="timeSystem"
|
:time-system="timeSystem"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -190,6 +190,10 @@ export default {
|
|||||||
start: offsets && durationFormatter.format(Math.abs(offsets.start)),
|
start: offsets && durationFormatter.format(Math.abs(offsets.start)),
|
||||||
end: offsets && durationFormatter.format(Math.abs(offsets.end))
|
end: offsets && durationFormatter.format(Math.abs(offsets.end))
|
||||||
},
|
},
|
||||||
|
bounds: {
|
||||||
|
start: bounds.start,
|
||||||
|
end: bounds.end
|
||||||
|
},
|
||||||
formattedBounds: {
|
formattedBounds: {
|
||||||
start: timeFormatter.format(bounds.start),
|
start: timeFormatter.format(bounds.start),
|
||||||
end: timeFormatter.format(bounds.end)
|
end: timeFormatter.format(bounds.end)
|
||||||
@ -210,7 +214,7 @@ export default {
|
|||||||
document.addEventListener('keydown', this.handleKeyDown);
|
document.addEventListener('keydown', this.handleKeyDown);
|
||||||
document.addEventListener('keyup', this.handleKeyUp);
|
document.addEventListener('keyup', this.handleKeyUp);
|
||||||
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));
|
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));
|
||||||
this.openmct.time.on('bounds', this.setViewFromBounds);
|
this.openmct.time.on('bounds', this.handleNewBounds);
|
||||||
this.openmct.time.on('timeSystem', this.setTimeSystem);
|
this.openmct.time.on('timeSystem', this.setTimeSystem);
|
||||||
this.openmct.time.on('clock', this.setViewFromClock);
|
this.openmct.time.on('clock', this.setViewFromClock);
|
||||||
this.openmct.time.on('clockOffsets', this.setViewFromOffsets);
|
this.openmct.time.on('clockOffsets', this.setViewFromOffsets);
|
||||||
@ -220,6 +224,13 @@ export default {
|
|||||||
document.removeEventListener('keyup', this.handleKeyUp);
|
document.removeEventListener('keyup', this.handleKeyUp);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handleNewBounds(bounds) {
|
||||||
|
this.setBounds(bounds);
|
||||||
|
this.setViewFromBounds(bounds);
|
||||||
|
},
|
||||||
|
setBounds(bounds) {
|
||||||
|
this.bounds = bounds;
|
||||||
|
},
|
||||||
handleKeyDown(event) {
|
handleKeyDown(event) {
|
||||||
if (event.key === 'Alt') {
|
if (event.key === 'Alt') {
|
||||||
this.altPressed = true;
|
this.altPressed = true;
|
||||||
@ -246,10 +257,13 @@ export default {
|
|||||||
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
|
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
|
||||||
},
|
},
|
||||||
endZoom(bounds) {
|
endZoom(bounds) {
|
||||||
const _bounds = bounds ? bounds : this.openmct.time.bounds();
|
|
||||||
this.isZooming = false;
|
this.isZooming = false;
|
||||||
|
|
||||||
this.openmct.time.bounds(_bounds);
|
if (bounds) {
|
||||||
|
this.handleNewBounds(bounds);
|
||||||
|
} else {
|
||||||
|
this.setViewFromBounds(this.bounds);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setTimeSystem(timeSystem) {
|
setTimeSystem(timeSystem) {
|
||||||
this.timeSystem = timeSystem;
|
this.timeSystem = timeSystem;
|
||||||
|
@ -207,7 +207,7 @@ export default {
|
|||||||
this.$emit('panAxis', panBounds);
|
this.$emit('panAxis', panBounds);
|
||||||
},
|
},
|
||||||
endPan() {
|
endPan() {
|
||||||
const panBounds = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
|
const panBounds = this.isChangingViewBounds()
|
||||||
? this.getPanBounds()
|
? this.getPanBounds()
|
||||||
: undefined;
|
: undefined;
|
||||||
this.$emit('endPan', panBounds);
|
this.$emit('endPan', panBounds);
|
||||||
@ -251,16 +251,14 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
endZoom() {
|
endZoom() {
|
||||||
const zoomRange = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
|
let zoomBounds;
|
||||||
? this.getZoomRange()
|
if (this.isChangingViewBounds()) {
|
||||||
: undefined;
|
const zoomRange = this.getZoomRange();
|
||||||
|
zoomBounds = {
|
||||||
const zoomBounds = zoomRange
|
|
||||||
? {
|
|
||||||
start: this.scaleToBounds(zoomRange.start),
|
start: this.scaleToBounds(zoomRange.start),
|
||||||
end: this.scaleToBounds(zoomRange.end)
|
end: this.scaleToBounds(zoomRange.end)
|
||||||
}
|
};
|
||||||
: this.openmct.time.bounds();
|
}
|
||||||
|
|
||||||
this.zoomStyle = {};
|
this.zoomStyle = {};
|
||||||
this.$emit('endZoom', zoomBounds);
|
this.$emit('endZoom', zoomBounds);
|
||||||
@ -290,6 +288,9 @@ export default {
|
|||||||
|
|
||||||
return bounds.start + offset;
|
return bounds.start + offset;
|
||||||
},
|
},
|
||||||
|
isChangingViewBounds() {
|
||||||
|
return this.dragStartX && this.dragX && this.dragStartX !== this.dragX;
|
||||||
|
},
|
||||||
resize() {
|
resize() {
|
||||||
if (this.$refs.axisHolder.clientWidth !== this.width) {
|
if (this.$refs.axisHolder.clientWidth !== this.width) {
|
||||||
this.setAxisDimensions();
|
this.setAxisDimensions();
|
||||||
|
@ -84,7 +84,12 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
history: {}, // contains arrays of timespans {start, end}, array key is time system key
|
/**
|
||||||
|
* previous bounds entries available for easy re-use
|
||||||
|
* @history array of timespans
|
||||||
|
* @timespans {start, end} number representing timestamp
|
||||||
|
*/
|
||||||
|
history: this.getHistoryFromLocalStorage(),
|
||||||
presets: []
|
presets: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -111,22 +116,20 @@ export default {
|
|||||||
this.addTimespan();
|
this.addTimespan();
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
},
|
|
||||||
history: {
|
|
||||||
handler() {
|
|
||||||
this.persistHistoryToLocalStorage();
|
|
||||||
},
|
|
||||||
deep: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getHistoryFromLocalStorage();
|
this.initializeHistoryIfNoHistory();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getHistoryFromLocalStorage() {
|
getHistoryFromLocalStorage() {
|
||||||
if (localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY)) {
|
const localStorageHistory = localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY);
|
||||||
this.history = JSON.parse(localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY));
|
const history = localStorageHistory ? JSON.parse(localStorageHistory) : undefined;
|
||||||
} else {
|
|
||||||
|
return history;
|
||||||
|
},
|
||||||
|
initializeHistoryIfNoHistory() {
|
||||||
|
if (!this.history) {
|
||||||
this.history = {};
|
this.history = {};
|
||||||
this.persistHistoryToLocalStorage();
|
this.persistHistoryToLocalStorage();
|
||||||
}
|
}
|
||||||
@ -157,6 +160,8 @@ export default {
|
|||||||
|
|
||||||
currentHistory.unshift(timespan);
|
currentHistory.unshift(timespan);
|
||||||
this.history[key] = currentHistory;
|
this.history[key] = currentHistory;
|
||||||
|
|
||||||
|
this.persistHistoryToLocalStorage();
|
||||||
},
|
},
|
||||||
selectTimespan(timespan) {
|
selectTimespan(timespan) {
|
||||||
this.openmct.time.bounds(timespan);
|
this.openmct.time.bounds(timespan);
|
||||||
|
@ -81,7 +81,12 @@ export default {
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.openmct.objects.get('ROOT')
|
this.openmct.objects.get('ROOT')
|
||||||
.then(root => {
|
.then(root => {
|
||||||
return this.openmct.composition.get(root).load();
|
let composition = this.openmct.composition.get(root);
|
||||||
|
if (composition !== undefined) {
|
||||||
|
return composition.load();
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then(children => {
|
.then(children => {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
@ -45,6 +45,7 @@ class ApplicationRouter extends EventEmitter {
|
|||||||
super();
|
super();
|
||||||
this.routes = [];
|
this.routes = [];
|
||||||
this.started = false;
|
this.started = false;
|
||||||
|
this.locationBar = new LocationBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,13 +57,17 @@ class ApplicationRouter extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.started = true;
|
this.started = true;
|
||||||
let locationBar = new LocationBar();
|
|
||||||
locationBar.onChange(p => this.handleLocationChange(p));
|
this.locationBar.onChange(p => this.handleLocationChange(p));
|
||||||
locationBar.start({
|
this.locationBar.start({
|
||||||
root: location.pathname
|
root: location.pathname
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.locationBar.stop();
|
||||||
|
}
|
||||||
|
|
||||||
handleLocationChange(pathString) {
|
handleLocationChange(pathString) {
|
||||||
if (pathString[0] !== '/') {
|
if (pathString[0] !== '/') {
|
||||||
pathString = '/' + pathString;
|
pathString = '/' + pathString;
|
||||||
|
@ -135,7 +135,6 @@ export default {
|
|||||||
value = this.getFormValue(domainObject, toolbarItem);
|
value = this.getFormValue(domainObject, toolbarItem);
|
||||||
} else {
|
} else {
|
||||||
let values = [];
|
let values = [];
|
||||||
|
|
||||||
if (applicableSelectedItems) {
|
if (applicableSelectedItems) {
|
||||||
applicableSelectedItems.forEach(selectionPath => {
|
applicableSelectedItems.forEach(selectionPath => {
|
||||||
values.push(this.getPropertyValue(domainObject, toolbarItem, selectionPath));
|
values.push(this.getPropertyValue(domainObject, toolbarItem, selectionPath));
|
||||||
@ -207,7 +206,6 @@ export default {
|
|||||||
},
|
},
|
||||||
updateObjectValue(value, item) {
|
updateObjectValue(value, item) {
|
||||||
let changedItemId = this.openmct.objects.makeKeyString(item.domainObject.identifier);
|
let changedItemId = this.openmct.objects.makeKeyString(item.domainObject.identifier);
|
||||||
|
|
||||||
this.structure = this.structure.map(toolbarItem => {
|
this.structure = this.structure.map(toolbarItem => {
|
||||||
if (toolbarItem.domainObject) {
|
if (toolbarItem.domainObject) {
|
||||||
let id = this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier);
|
let id = this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier);
|
||||||
|
@ -32,7 +32,6 @@ import {
|
|||||||
import {resetApplicationState} from 'utils/testing';
|
import {resetApplicationState} from 'utils/testing';
|
||||||
|
|
||||||
describe('the openmct location utility functions', () => {
|
describe('the openmct location utility functions', () => {
|
||||||
beforeAll(() => resetApplicationState());
|
|
||||||
afterEach(() => resetApplicationState());
|
afterEach(() => resetApplicationState());
|
||||||
|
|
||||||
it('The setSearchParam function sets an individual search parameters in the window location hash', () => {
|
it('The setSearchParam function sets an individual search parameters in the window location hash', () => {
|
||||||
|
@ -65,12 +65,29 @@ export function clearBuiltinSpies() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function resetApplicationState(openmct) {
|
export function resetApplicationState(openmct) {
|
||||||
|
let promise;
|
||||||
|
|
||||||
clearBuiltinSpies();
|
clearBuiltinSpies();
|
||||||
window.location.hash = '#';
|
|
||||||
|
|
||||||
if (openmct !== undefined) {
|
if (openmct !== undefined) {
|
||||||
openmct.destroy();
|
openmct.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window.location.hash !== '#' && window.location.hash !== '') {
|
||||||
|
promise = new Promise((resolve, reject) => {
|
||||||
|
window.addEventListener('hashchange', cleanup);
|
||||||
|
window.location.hash = '#';
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
window.removeEventListener('hashchange', cleanup);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
promise = Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearBuiltinSpy(funcDefinition) {
|
function clearBuiltinSpy(funcDefinition) {
|
||||||
|
Reference in New Issue
Block a user