mirror of
https://github.com/nasa/openmct.git
synced 2025-04-16 15:29:20 +00:00
[MyItems Plugin] Migrate/remove legacy MyItems code into new plugin (#4107)
* removed legacy my items, created my items plugin, moved relevant code to new plugin * added object api method for checking if a domainObject is a missing object Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
1680c3cc1b
commit
b8fabb7e73
@ -28,7 +28,6 @@ define([
|
||||
"./src/models/ModelCacheService",
|
||||
"./src/models/PersistedModelProvider",
|
||||
"./src/models/CachingModelDecorator",
|
||||
"./src/models/MissingModelDecorator",
|
||||
"./src/types/TypeProvider",
|
||||
"./src/actions/ActionProvider",
|
||||
"./src/actions/ActionAggregator",
|
||||
@ -57,7 +56,6 @@ define([
|
||||
ModelCacheService,
|
||||
PersistedModelProvider,
|
||||
CachingModelDecorator,
|
||||
MissingModelDecorator,
|
||||
TypeProvider,
|
||||
ActionProvider,
|
||||
ActionAggregator,
|
||||
@ -148,12 +146,6 @@ define([
|
||||
"cacheService"
|
||||
]
|
||||
},
|
||||
{
|
||||
"provides": "modelService",
|
||||
"type": "decorator",
|
||||
"priority": "fallback",
|
||||
"implementation": MissingModelDecorator
|
||||
},
|
||||
{
|
||||
"provides": "typeService",
|
||||
"type": "provider",
|
||||
|
@ -1,62 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Adds placeholder domain object models for any models which
|
||||
* fail to load from the underlying model service.
|
||||
* @constructor
|
||||
* @memberof platform/core
|
||||
* @param {ModelService} modelService this service to decorate
|
||||
* @implements {ModelService}
|
||||
*/
|
||||
function MissingModelDecorator(modelService) {
|
||||
this.modelService = modelService;
|
||||
}
|
||||
|
||||
function missingModel(id) {
|
||||
return {
|
||||
type: "unknown",
|
||||
name: "Missing: " + id
|
||||
};
|
||||
}
|
||||
|
||||
MissingModelDecorator.prototype.getModels = function (ids) {
|
||||
function addMissingModels(models) {
|
||||
var result = {};
|
||||
ids.forEach(function (id) {
|
||||
result[id] = models[id] || missingModel(id);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return this.modelService.getModels(ids).then(addMissingModels);
|
||||
};
|
||||
|
||||
return MissingModelDecorator;
|
||||
}
|
||||
);
|
||||
|
@ -1,86 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["../../src/models/MissingModelDecorator"],
|
||||
function (MissingModelDecorator) {
|
||||
|
||||
describe("The missing model decorator", function () {
|
||||
var mockModelService,
|
||||
testModels,
|
||||
decorator;
|
||||
|
||||
function asPromise(value) {
|
||||
return (value || {}).then ? value : {
|
||||
then: function (callback) {
|
||||
return asPromise(callback(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockModelService = jasmine.createSpyObj(
|
||||
"modelService",
|
||||
["getModels"]
|
||||
);
|
||||
|
||||
testModels = {
|
||||
testId: { someKey: "some value" }
|
||||
};
|
||||
|
||||
mockModelService.getModels.and.returnValue(asPromise(testModels));
|
||||
|
||||
decorator = new MissingModelDecorator(mockModelService);
|
||||
});
|
||||
|
||||
it("delegates to the wrapped model service", function () {
|
||||
decorator.getModels(['a', 'b', 'c']);
|
||||
expect(mockModelService.getModels)
|
||||
.toHaveBeenCalledWith(['a', 'b', 'c']);
|
||||
});
|
||||
|
||||
it("provides models for any IDs which are missing", function () {
|
||||
var models;
|
||||
decorator.getModels(['testId', 'otherId'])
|
||||
.then(function (m) {
|
||||
models = m;
|
||||
});
|
||||
expect(models.otherId).toBeDefined();
|
||||
});
|
||||
|
||||
it("does not overwrite existing models", function () {
|
||||
var models;
|
||||
decorator.getModels(['testId', 'otherId'])
|
||||
.then(function (m) {
|
||||
models = m;
|
||||
});
|
||||
expect(models.testId).toEqual({ someKey: "some value" });
|
||||
});
|
||||
|
||||
it("does not modify the wrapped service's response", function () {
|
||||
decorator.getModels(['testId', 'otherId']);
|
||||
expect(testModels.otherId).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
);
|
@ -25,7 +25,6 @@ define([
|
||||
'./capabilities/AdapterCapability',
|
||||
'./directives/MCTView',
|
||||
'./services/Instantiate',
|
||||
'./services/MissingModelCompatibilityDecorator',
|
||||
'./capabilities/APICapabilityDecorator',
|
||||
'./policies/AdaptedViewPolicy',
|
||||
'./runs/AlternateCompositionInitializer',
|
||||
@ -41,7 +40,6 @@ define([
|
||||
AdapterCapability,
|
||||
MCTView,
|
||||
Instantiate,
|
||||
MissingModelCompatibilityDecorator,
|
||||
APICapabilityDecorator,
|
||||
AdaptedViewPolicy,
|
||||
AlternateCompositionInitializer,
|
||||
@ -97,12 +95,6 @@ define([
|
||||
implementation: ActionDialogDecorator,
|
||||
depends: ["openmct"]
|
||||
},
|
||||
{
|
||||
type: "decorator",
|
||||
provides: "modelService",
|
||||
implementation: MissingModelCompatibilityDecorator,
|
||||
depends: ["openmct"]
|
||||
},
|
||||
{
|
||||
provides: "objectService",
|
||||
type: "decorator",
|
||||
|
@ -133,9 +133,13 @@ define([
|
||||
|
||||
return this.objectService.getObjects([keyString])
|
||||
.then(function (results) {
|
||||
let model = results[keyString].getModel();
|
||||
if (results[keyString]) {
|
||||
let model = results[keyString].getModel();
|
||||
|
||||
return utils.toNewFormat(model, key);
|
||||
return utils.toNewFormat(model, key);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'objectUtils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
|
||||
/**
|
||||
* Compatibility decorator for New API.
|
||||
*
|
||||
* When the model service returns no results, this attempts to load
|
||||
* the model from the new Object API and returns that instead. In order
|
||||
* to prevent infinite recursion, this only tries to fetch from the API
|
||||
* a single time.
|
||||
*
|
||||
*/
|
||||
function MissingModelCompatibilityDecorator(api, modelService) {
|
||||
this.api = api;
|
||||
this.modelService = modelService;
|
||||
this.apiFetching = {}; // to prevent loops, if we have already
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a set of ids from the public api and return a promise for their
|
||||
* models. If a model is requested twice, respond with a missing result.
|
||||
*/
|
||||
MissingModelCompatibilityDecorator.prototype.apiFetch = function (ids) {
|
||||
const results = {};
|
||||
|
||||
const promises = ids.map(function (id) {
|
||||
if (this.apiFetching[id]) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this.apiFetching[id] = true;
|
||||
|
||||
return this.api.objects.get(objectUtils.parseKeyString(id))
|
||||
.then(function (newDO) {
|
||||
results[id] = objectUtils.toOldFormat(newDO);
|
||||
});
|
||||
}, this);
|
||||
|
||||
return Promise.all(promises).then(function () {
|
||||
return results;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a promise for model results based on provided ids. Will attempt
|
||||
* to fetch any missing results from the object api.
|
||||
*/
|
||||
MissingModelCompatibilityDecorator.prototype.getModels = function (ids) {
|
||||
return this.modelService.getModels(ids)
|
||||
.then(function (models) {
|
||||
const missingIds = ids.filter(function (id) {
|
||||
return !models[id];
|
||||
});
|
||||
|
||||
if (!missingIds.length) {
|
||||
return models;
|
||||
}
|
||||
|
||||
//Temporary fix for missing models - don't retry using this.apiFetch
|
||||
return models;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
return MissingModelCompatibilityDecorator;
|
||||
});
|
||||
|
@ -302,6 +302,13 @@ ObjectAPI.prototype.isPersistable = function (idOrKeyString) {
|
||||
&& provider.update !== undefined;
|
||||
};
|
||||
|
||||
ObjectAPI.prototype.isMissing = function (domainObject) {
|
||||
let identifier = utils.makeKeyString(domainObject.identifier);
|
||||
let missingName = 'Missing: ' + identifier;
|
||||
|
||||
return domainObject.name === missingName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Save this domain object in its current state. EXPERIMENTAL
|
||||
*
|
||||
|
@ -78,7 +78,6 @@ define([
|
||||
'../platform/execution/bundle',
|
||||
'../platform/exporters/bundle',
|
||||
'../platform/features/clock/bundle',
|
||||
'../platform/features/my-items/bundle',
|
||||
'../platform/features/static-markup/bundle',
|
||||
'../platform/forms/bundle',
|
||||
'../platform/framework/bundle',
|
||||
|
@ -23,7 +23,7 @@
|
||||
export default function MissingObjectInterceptor(openmct) {
|
||||
openmct.objects.addGetInterceptor({
|
||||
appliesTo: (identifier, domainObject) => {
|
||||
return identifier.key !== 'mine';
|
||||
return true;
|
||||
},
|
||||
invoke: (identifier, object) => {
|
||||
if (object === undefined) {
|
||||
|
@ -1,9 +1,7 @@
|
||||
import missingObjectInterceptor from "./missingObjectInterceptor";
|
||||
import myItemsInterceptor from "./myItemsInterceptor";
|
||||
|
||||
export default function plugin() {
|
||||
return function install(openmct) {
|
||||
myItemsInterceptor(openmct);
|
||||
missingObjectInterceptor(openmct);
|
||||
};
|
||||
}
|
||||
|
@ -75,22 +75,5 @@ describe('the plugin', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the My items object if not found', () => {
|
||||
const identifier = {
|
||||
namespace: TEST_NAMESPACE,
|
||||
key: 'mine'
|
||||
};
|
||||
|
||||
return openmct.objects.get(identifier).then((testObject) => {
|
||||
expect(testObject).toEqual({
|
||||
identifier,
|
||||
"name": "My Items",
|
||||
"type": "folder",
|
||||
"composition": [],
|
||||
"location": "ROOT"
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
8
src/plugins/myItems/createMyItemsIdentifier.js
Normal file
8
src/plugins/myItems/createMyItemsIdentifier.js
Normal file
@ -0,0 +1,8 @@
|
||||
export const MY_ITEMS_KEY = 'mine';
|
||||
|
||||
export function createMyItemsIdentifier(namespace = '') {
|
||||
return {
|
||||
key: MY_ITEMS_KEY,
|
||||
namespace
|
||||
};
|
||||
}
|
@ -20,24 +20,30 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
export default function MyItemsInterceptor(openmct) {
|
||||
import { MY_ITEMS_KEY } from "./createMyItemsIdentifier";
|
||||
|
||||
openmct.objects.addGetInterceptor({
|
||||
appliesTo: (identifier, domainObject) => {
|
||||
return identifier.key === 'mine';
|
||||
function myItemsInterceptor(identifierObject, openmct) {
|
||||
|
||||
const myItemsModel = {
|
||||
identifier: identifierObject,
|
||||
"name": "My Items",
|
||||
"type": "folder",
|
||||
"composition": [],
|
||||
"location": "ROOT"
|
||||
};
|
||||
|
||||
return {
|
||||
appliesTo: (identifier) => {
|
||||
return identifier.key === MY_ITEMS_KEY;
|
||||
},
|
||||
invoke: (identifier, object) => {
|
||||
if (object === undefined) {
|
||||
return {
|
||||
identifier,
|
||||
"name": "My Items",
|
||||
"type": "folder",
|
||||
"composition": [],
|
||||
"location": "ROOT"
|
||||
};
|
||||
if (openmct.objects.isMissing(object)) {
|
||||
return myItemsModel;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default myItemsInterceptor;
|
@ -20,30 +20,14 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([], function () {
|
||||
return {
|
||||
name: "platform/features/my-items",
|
||||
definition: {
|
||||
"name": "My Items",
|
||||
"description": "Defines a root named My Items",
|
||||
"extensions": {
|
||||
"roots": [
|
||||
{
|
||||
"id": "mine"
|
||||
}
|
||||
],
|
||||
"models": [
|
||||
{
|
||||
"id": "mine",
|
||||
"model": {
|
||||
"name": "My Items",
|
||||
"type": "folder",
|
||||
"composition": [],
|
||||
"location": "ROOT"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
import { createMyItemsIdentifier } from "./createMyItemsIdentifier";
|
||||
import myItemsInterceptor from "./myItemsInterceptor";
|
||||
|
||||
export default function MyItemsPlugin(namespace = '') {
|
||||
return function install(openmct) {
|
||||
const identifier = createMyItemsIdentifier(namespace);
|
||||
|
||||
openmct.objects.addGetInterceptor(myItemsInterceptor(identifier, openmct));
|
||||
openmct.objects.addRoot(identifier);
|
||||
};
|
||||
});
|
||||
}
|
90
src/plugins/myItems/pluginSpec.js
Normal file
90
src/plugins/myItems/pluginSpec.js
Normal file
@ -0,0 +1,90 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import {
|
||||
createOpenMct,
|
||||
resetApplicationState
|
||||
} from 'utils/testing';
|
||||
import {
|
||||
createMyItemsIdentifier,
|
||||
MY_ITEMS_KEY
|
||||
} from './createMyItemsIdentifier';
|
||||
|
||||
const MISSING_NAME = `Missing: ${MY_ITEMS_KEY}`;
|
||||
const myItemsIdentifier = createMyItemsIdentifier();
|
||||
|
||||
describe("the plugin", () => {
|
||||
let openmct;
|
||||
let missingObj = {
|
||||
identifier: myItemsIdentifier,
|
||||
type: 'unknown',
|
||||
name: MISSING_NAME
|
||||
};
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
|
||||
openmct.install(openmct.plugins.MyItems());
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
return resetApplicationState(openmct);
|
||||
});
|
||||
|
||||
it('when installed, adds "My Items" to the root', async () => {
|
||||
const root = await openmct.objects.get('ROOT');
|
||||
const rootCompostionCollection = openmct.composition.get(root);
|
||||
const rootCompostion = await rootCompostionCollection.load();
|
||||
let myItems = rootCompostion.filter((domainObject) => {
|
||||
return openmct.objects.areIdsEqual(domainObject.identifier, myItemsIdentifier);
|
||||
})[0];
|
||||
|
||||
expect(myItems).toBeDefined();
|
||||
});
|
||||
|
||||
describe('adds an interceptor that returns a "My Items" model for', () => {
|
||||
let myItemsMissing;
|
||||
let mockMissingProvider;
|
||||
let activeProvider;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockMissingProvider = {
|
||||
get: () => Promise.resolve(missingObj)
|
||||
};
|
||||
|
||||
activeProvider = mockMissingProvider;
|
||||
spyOn(openmct.objects, 'getProvider').and.returnValue(activeProvider);
|
||||
myItemsMissing = await openmct.objects.get(myItemsIdentifier);
|
||||
});
|
||||
|
||||
it('missing objects', () => {
|
||||
let idsMatchMissing = openmct.objects.areIdsEqual(myItemsMissing.identifier, myItemsIdentifier);
|
||||
|
||||
expect(myItemsMissing).toBeDefined();
|
||||
expect(idsMatchMissing).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -26,6 +26,7 @@ define([
|
||||
'./remoteClock/plugin',
|
||||
'./localTimeSystem/plugin',
|
||||
'./ISOTimeFormat/plugin',
|
||||
'./myItems/plugin',
|
||||
'../../example/generator/plugin',
|
||||
'./autoflow/AutoflowTabularPlugin',
|
||||
'./timeConductor/plugin',
|
||||
@ -78,6 +79,7 @@ define([
|
||||
RemoteClock,
|
||||
LocalTimeSystem,
|
||||
ISOTimeFormat,
|
||||
MyItems,
|
||||
GeneratorPlugin,
|
||||
AutoflowPlugin,
|
||||
TimeConductorPlugin,
|
||||
@ -127,7 +129,6 @@ define([
|
||||
) {
|
||||
const bundleMap = {
|
||||
LocalStorage: 'platform/persistence/local',
|
||||
MyItems: 'platform/features/my-items',
|
||||
Elasticsearch: 'platform/persistence/elastic'
|
||||
};
|
||||
|
||||
@ -143,6 +144,8 @@ define([
|
||||
plugins.LocalTimeSystem = LocalTimeSystem;
|
||||
plugins.RemoteClock = RemoteClock.default;
|
||||
|
||||
plugins.MyItems = MyItems.default;
|
||||
|
||||
plugins.ImportExport = ImportExport;
|
||||
|
||||
plugins.StaticRootPlugin = StaticRootPlugin;
|
||||
|
Loading…
x
Reference in New Issue
Block a user