Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nasa/openmct.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeep Tailor <deep.j.tailor@nasa.gov>2020-12-02 01:42:35 +0300
committerDeep Tailor <deep.j.tailor@nasa.gov>2020-12-02 01:42:35 +0300
commitcb8e906f930dedd443bd13aa1719ddd7b8250847 (patch)
tree6833c9b4545993827f5cc915ff435229e6cac9c0
parentbe746db7749c4b140d1c510f60e77c67b5e3fd2c (diff)
parent1c2b0678bebeadb2fd5e84b9554bf57eef99acc1 (diff)
Merge branch 'master' of https://github.com/nasa/openmct into regex-search-tablesv1.4.0-rc6
-rw-r--r--src/MCT.js1
-rw-r--r--src/api/objects/InterceptorRegistry.js66
-rw-r--r--src/api/objects/InterceptorRegistrySpec.js0
-rw-r--r--src/api/objects/ObjectAPI.js28
-rw-r--r--src/api/objects/ObjectAPISpec.js48
-rw-r--r--src/plugins/duplicate/DuplicateAction.js5
-rw-r--r--src/plugins/interceptors/missingObjectInterceptor.js40
-rw-r--r--src/plugins/interceptors/myItemsInterceptor.js43
-rw-r--r--src/plugins/interceptors/plugin.js9
-rw-r--r--src/plugins/move/MoveAction.js3
-rw-r--r--src/plugins/persistence/couch/CouchObjectProvider.js3
-rw-r--r--src/plugins/plot/src/services/ExportImageService.js14
-rw-r--r--src/plugins/plugins.js7
-rw-r--r--src/plugins/telemetryTable/ViewActions.js6
-rw-r--r--src/plugins/telemetryTable/components/table.vue2
-rw-r--r--src/ui/components/object-frame.scss2
16 files changed, 266 insertions, 11 deletions
diff --git a/src/MCT.js b/src/MCT.js
index a5d6ce88b..8e8f8ee21 100644
--- a/src/MCT.js
+++ b/src/MCT.js
@@ -282,6 +282,7 @@ define([
this.install(this.plugins.NotificationIndicator());
this.install(this.plugins.NewFolderAction());
this.install(this.plugins.ViewDatumAction());
+ this.install(this.plugins.ObjectInterceptors());
}
MCT.prototype = Object.create(EventEmitter.prototype);
diff --git a/src/api/objects/InterceptorRegistry.js b/src/api/objects/InterceptorRegistry.js
new file mode 100644
index 000000000..f8a44326d
--- /dev/null
+++ b/src/api/objects/InterceptorRegistry.js
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+export default class InterceptorRegistry {
+ /**
+ * A InterceptorRegistry maintains the definitions for different interceptors that may be invoked on domain objects.
+ * @interface InterceptorRegistry
+ * @memberof module:openmct
+ */
+ constructor() {
+ this.interceptors = [];
+ }
+
+ /**
+ * @interface InterceptorDef
+ * @property {function} appliesTo function that determines if this interceptor should be called for the given identifier/object
+ * @property {function} invoke function that transforms the provided domain object and returns the transformed domain object
+ * @property {function} priority the priority for this interceptor. A higher number returned has more weight than a lower number
+ * @memberof module:openmct InterceptorRegistry#
+ */
+
+ /**
+ * Register a new object interceptor.
+ *
+ * @param {module:openmct.InterceptorDef} interceptorDef the interceptor to add
+ * @method addInterceptor
+ * @memberof module:openmct.InterceptorRegistry#
+ */
+ addInterceptor(interceptorDef) {
+ //TODO: sort by priority
+ this.interceptors.push(interceptorDef);
+ }
+
+ /**
+ * Retrieve all interceptors applicable to a domain object.
+ * @method getInterceptors
+ * @returns [module:openmct.InterceptorDef] the registered interceptors for this identifier/object
+ * @memberof module:openmct.InterceptorRegistry#
+ */
+ getInterceptors(identifier, object) {
+ return this.interceptors.filter(interceptor => {
+ return typeof interceptor.appliesTo === 'function'
+ && interceptor.appliesTo(identifier, object);
+ });
+ }
+
+}
+
diff --git a/src/api/objects/InterceptorRegistrySpec.js b/src/api/objects/InterceptorRegistrySpec.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/api/objects/InterceptorRegistrySpec.js
diff --git a/src/api/objects/ObjectAPI.js b/src/api/objects/ObjectAPI.js
index 7fb21d89a..c2747be61 100644
--- a/src/api/objects/ObjectAPI.js
+++ b/src/api/objects/ObjectAPI.js
@@ -26,6 +26,7 @@ define([
'./MutableObject',
'./RootRegistry',
'./RootObjectProvider',
+ './InterceptorRegistry',
'EventEmitter'
], function (
_,
@@ -33,6 +34,7 @@ define([
MutableObject,
RootRegistry,
RootObjectProvider,
+ InterceptorRegistry,
EventEmitter
) {
@@ -48,6 +50,7 @@ define([
this.rootRegistry = new RootRegistry();
this.rootProvider = new RootObjectProvider.default(this.rootRegistry);
this.cache = {};
+ this.interceptorRegistry = new InterceptorRegistry.default();
}
/**
@@ -177,6 +180,10 @@ define([
return objectPromise.then(result => {
delete this.cache[keystring];
+ const interceptors = this.listGetInterceptors(identifier, result);
+ interceptors.forEach(interceptor => {
+ result = interceptor.invoke(identifier, result);
+ });
return result;
});
@@ -313,6 +320,27 @@ define([
};
/**
+ * Register an object interceptor that transforms a domain object requested via module:openmct.ObjectAPI.get
+ * The domain object will be transformed after it is retrieved from the persistence store
+ * The domain object will be transformed only if the interceptor is applicable to that domain object as defined by the InterceptorDef
+ *
+ * @param {module:openmct.InterceptorDef} interceptorDef the interceptor definition to add
+ * @method addGetInterceptor
+ * @memberof module:openmct.InterceptorRegistry#
+ */
+ ObjectAPI.prototype.addGetInterceptor = function (interceptorDef) {
+ this.interceptorRegistry.addInterceptor(interceptorDef);
+ };
+
+ /**
+ * Retrieve the interceptors for a given domain object.
+ * @private
+ */
+ ObjectAPI.prototype.listGetInterceptors = function (identifier, object) {
+ return this.interceptorRegistry.getInterceptors(identifier, object);
+ };
+
+ /**
* Uniquely identifies a domain object.
*
* @typedef Identifier
diff --git a/src/api/objects/ObjectAPISpec.js b/src/api/objects/ObjectAPISpec.js
index 22c037a50..ad6293b72 100644
--- a/src/api/objects/ObjectAPISpec.js
+++ b/src/api/objects/ObjectAPISpec.js
@@ -63,12 +63,51 @@ describe("The Object API", () => {
describe("The get function", () => {
describe("when a provider is available", () => {
let mockProvider;
+ let mockInterceptor;
+ let anotherMockInterceptor;
+ let notApplicableMockInterceptor;
beforeEach(() => {
mockProvider = jasmine.createSpyObj("mock provider", [
"get"
]);
mockProvider.get.and.returnValue(Promise.resolve(mockDomainObject));
+
+ mockInterceptor = jasmine.createSpyObj("mock interceptor", [
+ "appliesTo",
+ "invoke"
+ ]);
+ mockInterceptor.appliesTo.and.returnValue(true);
+ mockInterceptor.invoke.and.callFake((identifier, object) => {
+ return Object.assign({
+ changed: true
+ }, object);
+ });
+
+ anotherMockInterceptor = jasmine.createSpyObj("another mock interceptor", [
+ "appliesTo",
+ "invoke"
+ ]);
+ anotherMockInterceptor.appliesTo.and.returnValue(true);
+ anotherMockInterceptor.invoke.and.callFake((identifier, object) => {
+ return Object.assign({
+ alsoChanged: true
+ }, object);
+ });
+
+ notApplicableMockInterceptor = jasmine.createSpyObj("not applicable mock interceptor", [
+ "appliesTo",
+ "invoke"
+ ]);
+ notApplicableMockInterceptor.appliesTo.and.returnValue(false);
+ notApplicableMockInterceptor.invoke.and.callFake((identifier, object) => {
+ return Object.assign({
+ shouldNotBeChanged: true
+ }, object);
+ });
objectAPI.addProvider(TEST_NAMESPACE, mockProvider);
+ objectAPI.addGetInterceptor(mockInterceptor);
+ objectAPI.addGetInterceptor(anotherMockInterceptor);
+ objectAPI.addGetInterceptor(notApplicableMockInterceptor);
});
it("Caches multiple requests for the same object", () => {
@@ -78,6 +117,15 @@ describe("The Object API", () => {
objectAPI.get(mockDomainObject.identifier);
expect(mockProvider.get.calls.count()).toBe(1);
});
+
+ it("applies any applicable interceptors", () => {
+ expect(mockDomainObject.changed).toBeUndefined();
+ objectAPI.get(mockDomainObject.identifier).then((object) => {
+ expect(object.changed).toBeTrue();
+ expect(object.alsoChanged).toBeTrue();
+ expect(object.shouldNotBeChanged).toBeUndefined();
+ });
+ });
});
});
});
diff --git a/src/plugins/duplicate/DuplicateAction.js b/src/plugins/duplicate/DuplicateAction.js
index e398b6c04..57d7e7f33 100644
--- a/src/plugins/duplicate/DuplicateAction.js
+++ b/src/plugins/duplicate/DuplicateAction.js
@@ -143,13 +143,16 @@ export default class DuplicateAction {
let parent = objectPath[1];
let parentType = parent && this.openmct.types.get(parent.type);
let child = objectPath[0];
+ let childType = child && this.openmct.types.get(child.type);
let locked = child.locked ? child.locked : parent && parent.locked;
if (locked) {
return false;
}
- return parentType
+ return childType
+ && childType.definition.creatable
+ && parentType
&& parentType.definition.creatable
&& Array.isArray(parent.composition);
}
diff --git a/src/plugins/interceptors/missingObjectInterceptor.js b/src/plugins/interceptors/missingObjectInterceptor.js
new file mode 100644
index 000000000..029b65bf4
--- /dev/null
+++ b/src/plugins/interceptors/missingObjectInterceptor.js
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+
+export default function MissingObjectInterceptor(openmct) {
+ openmct.objects.addGetInterceptor({
+ appliesTo: (identifier, domainObject) => {
+ return identifier.key !== 'mine';
+ },
+ invoke: (identifier, object) => {
+ if (object === undefined) {
+ return {
+ identifier,
+ type: 'unknown',
+ name: 'Missing: ' + openmct.objects.makeKeyString(identifier)
+ };
+ }
+
+ return object;
+ }
+ });
+}
diff --git a/src/plugins/interceptors/myItemsInterceptor.js b/src/plugins/interceptors/myItemsInterceptor.js
new file mode 100644
index 000000000..ef92839e5
--- /dev/null
+++ b/src/plugins/interceptors/myItemsInterceptor.js
@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+
+export default function MyItemsInterceptor(openmct) {
+
+ openmct.objects.addGetInterceptor({
+ appliesTo: (identifier, domainObject) => {
+ return identifier.key === 'mine';
+ },
+ invoke: (identifier, object) => {
+ if (object === undefined) {
+ return {
+ identifier,
+ "name": "My Items",
+ "type": "folder",
+ "composition": [],
+ "location": "ROOT"
+ };
+ }
+
+ return object;
+ }
+ });
+}
diff --git a/src/plugins/interceptors/plugin.js b/src/plugins/interceptors/plugin.js
new file mode 100644
index 000000000..446010094
--- /dev/null
+++ b/src/plugins/interceptors/plugin.js
@@ -0,0 +1,9 @@
+import missingObjectInterceptor from "./missingObjectInterceptor";
+import myItemsInterceptor from "./myItemsInterceptor";
+
+export default function plugin() {
+ return function install(openmct) {
+ myItemsInterceptor(openmct);
+ missingObjectInterceptor(openmct);
+ };
+}
diff --git a/src/plugins/move/MoveAction.js b/src/plugins/move/MoveAction.js
index 2a4605307..8b46d109f 100644
--- a/src/plugins/move/MoveAction.js
+++ b/src/plugins/move/MoveAction.js
@@ -154,6 +154,7 @@ export default class MoveAction {
let parent = objectPath[1];
let parentType = parent && this.openmct.types.get(parent.type);
let child = objectPath[0];
+ let childType = child && this.openmct.types.get(child.type);
if (child.locked || (parent && parent.locked)) {
return false;
@@ -161,6 +162,8 @@ export default class MoveAction {
return parentType
&& parentType.definition.creatable
+ && childType
+ && childType.definition.creatable
&& Array.isArray(parent.composition);
}
}
diff --git a/src/plugins/persistence/couch/CouchObjectProvider.js b/src/plugins/persistence/couch/CouchObjectProvider.js
index 1df673eb7..8c7c4d3bf 100644
--- a/src/plugins/persistence/couch/CouchObjectProvider.js
+++ b/src/plugins/persistence/couch/CouchObjectProvider.js
@@ -87,7 +87,8 @@ export default class CouchObjectProvider {
}
//Sometimes CouchDB returns the old rev which fetching the object if there is a document update in progress
- if (!this.objectQueue[key].pending) {
+ //Only update the rev if it's the first time we're getting the object from CouchDB. Subsequent revs should only be updated by updates.
+ if (!this.objectQueue[key].pending && !this.objectQueue[key].rev) {
this.objectQueue[key].updateRevision(response[REV]);
}
diff --git a/src/plugins/plot/src/services/ExportImageService.js b/src/plugins/plot/src/services/ExportImageService.js
index 74967a577..7373b6a9e 100644
--- a/src/plugins/plot/src/services/ExportImageService.js
+++ b/src/plugins/plot/src/services/ExportImageService.js
@@ -117,8 +117,10 @@ define(
* @returns {promise}
*/
ExportImageService.prototype.exportJPG = function (element, filename, className) {
+ const processedFilename = replaceDotsWithUnderscores(filename);
+
return this.renderElement(element, "jpg", className).then(function (img) {
- saveAs(img, filename);
+ saveAs(img, processedFilename);
});
};
@@ -130,8 +132,10 @@ define(
* @returns {promise}
*/
ExportImageService.prototype.exportPNG = function (element, filename, className) {
+ const processedFilename = replaceDotsWithUnderscores(filename);
+
return this.renderElement(element, "png", className).then(function (img) {
- saveAs(img, filename);
+ saveAs(img, processedFilename);
});
};
@@ -146,6 +150,12 @@ define(
return this.renderElement(element, "png", className);
};
+ function replaceDotsWithUnderscores(filename) {
+ const regex = /\./gi;
+
+ return filename.replace(regex, '_');
+ }
+
/**
* canvas.toBlob() not supported in IE < 10, Opera, and Safari. This polyfill
* implements the method in browsers that would not otherwise support it.
diff --git a/src/plugins/plugins.js b/src/plugins/plugins.js
index 03be9ec6c..875918f8d 100644
--- a/src/plugins/plugins.js
+++ b/src/plugins/plugins.js
@@ -59,7 +59,8 @@ define([
'./persistence/couch/plugin',
'./defaultRootName/plugin',
'./timeline/plugin',
- './viewDatumAction/plugin'
+ './viewDatumAction/plugin',
+ './interceptors/plugin'
], function (
_,
UTCTimeSystem,
@@ -99,7 +100,8 @@ define([
CouchDBPlugin,
DefaultRootName,
Timeline,
- ViewDatumAction
+ ViewDatumAction,
+ ObjectInterceptors
) {
const bundleMap = {
LocalStorage: 'platform/persistence/local',
@@ -194,6 +196,7 @@ define([
plugins.DefaultRootName = DefaultRootName.default;
plugins.Timeline = Timeline.default;
plugins.ViewDatumAction = ViewDatumAction.default;
+ plugins.ObjectInterceptors = ObjectInterceptors.default;
return plugins;
});
diff --git a/src/plugins/telemetryTable/ViewActions.js b/src/plugins/telemetryTable/ViewActions.js
index d4d8212ca..8d438fc5d 100644
--- a/src/plugins/telemetryTable/ViewActions.js
+++ b/src/plugins/telemetryTable/ViewActions.js
@@ -30,13 +30,13 @@ let exportCSV = {
},
group: 'view'
};
-let exportMarkedRows = {
+let exportMarkedDataAsCSV = {
name: 'Export Marked Rows',
key: 'export-csv-marked',
description: "Export marked rows as CSV",
cssClass: 'icon-download labeled',
invoke: (objectPath, viewProvider) => {
- viewProvider.getViewContext().exportMarkedRows();
+ viewProvider.getViewContext().exportMarkedDataAsCSV();
},
group: 'view'
};
@@ -98,7 +98,7 @@ let autosizeColumns = {
let viewActions = [
exportCSV,
- exportMarkedRows,
+ exportMarkedDataAsCSV,
unmarkAllRows,
pause,
play,
diff --git a/src/plugins/telemetryTable/components/table.vue b/src/plugins/telemetryTable/components/table.vue
index 98abacf6b..515a317e0 100644
--- a/src/plugins/telemetryTable/components/table.vue
+++ b/src/plugins/telemetryTable/components/table.vue
@@ -992,7 +992,7 @@ export default {
return {
type: 'telemetry-table',
exportAllDataAsCSV: this.exportAllDataAsCSV,
- exportMarkedRows: this.exportMarkedRows,
+ exportMarkedDataAsCSV: this.exportMarkedDataAsCSV,
unmarkAllRows: this.unmarkAllRows,
togglePauseByButton: this.togglePauseByButton,
expandColumns: this.recalculateColumnWidths,
diff --git a/src/ui/components/object-frame.scss b/src/ui/components/object-frame.scss
index 97df32cf8..4247f7999 100644
--- a/src/ui/components/object-frame.scss
+++ b/src/ui/components/object-frame.scss
@@ -162,5 +162,5 @@
// This element is the recipient for object styling; cannot be display: contents
flex: 1 1 auto;
overflow: hidden;
- display: contents;
+ display: block;
}