Remove legacy type service usage from modern Open MCT codebase (#4534)

* Remove type service from the DefaultMetadataProvider
* Added tests
* Move unknown types to new type registry
* Migrate legacy type telemetry information to new types to obviate need to use type service from new API
* Remove default object, it's not needed any more
* Remove injector from spec
This commit is contained in:
Andrew Henry 2021-12-15 19:36:01 -08:00 committed by GitHub
parent 1f588a2a6e
commit 01d02642e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 211 additions and 40 deletions

View File

@ -220,26 +220,6 @@ define([
"key": "root",
"name": "Root",
"cssClass": "icon-folder"
},
{
"key": "folder",
"name": "Folder",
"cssClass": "icon-folder",
"features": "creation",
"description": "Create folders to organize other objects or links to objects.",
"priority": 1000,
"model": {
"composition": []
}
},
{
"key": "unknown",
"name": "Unknown Type",
"cssClass": "icon-object-unknown"
},
{
"name": "Unknown Type",
"cssClass": "icon-object-unknown"
}
],
"capabilities": [

View File

@ -102,8 +102,10 @@ define([
DefaultMetadataProvider.prototype.getMetadata = function (domainObject) {
const metadata = domainObject.telemetry || {};
if (this.typeHasTelemetry(domainObject)) {
const typeMetadata = this.typeService.getType(domainObject.type).typeDef.telemetry;
const typeMetadata = this.openmct.types.get(domainObject.type).definition.telemetry;
Object.assign(metadata, typeMetadata);
if (!metadata.values) {
metadata.values = valueMetadatasFromOldFormat(metadata);
}
@ -116,11 +118,9 @@ define([
* @private
*/
DefaultMetadataProvider.prototype.typeHasTelemetry = function (domainObject) {
if (!this.typeService) {
this.typeService = this.openmct.$injector.get('typeService');
}
const type = this.openmct.types.get(domainObject.type);
return Boolean(this.typeService.getType(domainObject.type).typeDef.telemetry);
return Boolean(type.definition.telemetry);
};
return DefaultMetadataProvider;

View File

@ -27,7 +27,6 @@ describe('Telemetry API', function () {
const NO_PROVIDER = 'No provider found';
let openmct;
let telemetryAPI;
let mockTypeService;
beforeEach(function () {
openmct = {
@ -35,14 +34,11 @@ describe('Telemetry API', function () {
'timeSystem',
'bounds'
]),
$injector: jasmine.createSpyObj('injector', [
types: jasmine.createSpyObj('typeRegistry', [
'get'
])
};
mockTypeService = jasmine.createSpyObj('typeService', [
'getType'
]);
openmct.$injector.get.and.returnValue(mockTypeService);
openmct.time.timeSystem.and.returnValue({key: 'system'});
openmct.time.bounds.and.returnValue({
start: 0,
@ -356,7 +352,7 @@ describe('Telemetry API', function () {
describe('metadata', function () {
let mockMetadata = {};
let mockObjectType = {
typeDef: {}
definition: {}
};
beforeEach(function () {
telemetryAPI.addProvider({
@ -368,7 +364,7 @@ describe('Telemetry API', function () {
return mockMetadata;
}
});
mockTypeService.getType.and.returnValue(mockObjectType);
openmct.types.get.and.returnValue(mockObjectType);
});
it('respects explicit priority', function () {
@ -587,7 +583,7 @@ describe('Telemetry API', function () {
let domainObject;
let mockMetadata = {};
let mockObjectType = {
typeDef: {}
definition: {}
};
beforeEach(function () {
@ -601,7 +597,7 @@ describe('Telemetry API', function () {
return mockMetadata;
}
});
mockTypeService.getType.and.returnValue(mockObjectType);
openmct.types.get.and.returnValue(mockObjectType);
domainObject = {
identifier: {
key: 'a',

View File

@ -82,6 +82,32 @@ define(function () {
definition.cssClass = legacyDefinition.cssClass;
definition.description = legacyDefinition.description;
definition.form = legacyDefinition.properties;
if (legacyDefinition.telemetry !== undefined) {
let telemetry = {
values: []
};
if (legacyDefinition.telemetry.domains !== undefined) {
legacyDefinition.telemetry.domains.forEach((domain, index) => {
domain.hints = {
domain: index
};
telemetry.values.push(domain);
});
}
if (legacyDefinition.telemetry.ranges !== undefined) {
legacyDefinition.telemetry.ranges.forEach((range, index) => {
range.hints = {
range: index
};
telemetry.values.push(range);
});
}
definition.telemetry = telemetry;
}
if (legacyDefinition.model) {
definition.initialize = function (model) {
for (let [k, v] of Object.entries(legacyDefinition.model)) {

View File

@ -19,8 +19,13 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(['./Type'], function (Type) {
const UNKNOWN_TYPE = new Type({
key: "unknown",
name: "Unknown Type",
cssClass: "icon-object-unknown"
});
/**
* @typedef TypeDefinition
* @memberof module:openmct.TypeRegistry~
@ -89,11 +94,11 @@ define(['./Type'], function (Type) {
* @returns {module:openmct.Type} the registered type
*/
TypeRegistry.prototype.get = function (typeKey) {
return this.types[typeKey];
return this.types[typeKey] || UNKNOWN_TYPE;
};
TypeRegistry.prototype.importLegacyTypes = function (types) {
types.filter((t) => !this.get(t.key))
types.filter((t) => this.get(t.key) === UNKNOWN_TYPE)
.forEach((type) => {
let def = Type.definitionFromLegacyDefinition(type);
this.addType(type.key, def);

View File

@ -1,6 +1,6 @@
<template>
<a
class="l-grid-view__item c-grid-item"
class="l-grid-view__item c-grid-item js-folder-child"
:class="[{
'is-alias': item.isAlias === true,
'c-grid-item--unknown': item.type.cssClass === undefined || item.type.cssClass.indexOf('unknown') !== -1

View File

@ -1,6 +1,6 @@
<template>
<tr
class="c-list-item"
class="c-list-item js-folder-child"
:class="{
'is-alias': item.isAlias === true
}"

View File

@ -29,6 +29,17 @@ define([
) {
return function plugin() {
return function install(openmct) {
openmct.types.addType('folder', {
name: "Folder",
key: "folder",
description: "Create folders to organize other objects or links to objects without the ability to edit it's properties.",
cssClass: "icon-folder",
creatable: true,
initialize: function (domainObject) {
domainObject.composition = [];
}
});
openmct.objectViews.addProvider(new FolderGridView(openmct));
openmct.objectViews.addProvider(new FolderListView(openmct));
};

View File

@ -0,0 +1,153 @@
/*****************************************************************************
* 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 FolderPlugin from './plugin.js';
import Vue from 'vue';
import {
createOpenMct,
resetApplicationState
} from 'utils/testing';
describe("The folder plugin", () => {
let openmct;
let folderPlugin;
beforeEach((done) => {
openmct = createOpenMct();
folderPlugin = new FolderPlugin();
openmct.install(folderPlugin);
openmct.on('start', done);
openmct.startHeadless();
});
afterEach(() => {
return resetApplicationState(openmct);
});
describe("the folder object type", () => {
let folderType;
beforeEach(() => {
folderType = openmct.types.get('folder');
});
it("is installed by the plugin", () => {
expect(folderType).toBeDefined();
});
it("is user creatable", () => {
expect(folderType.definition.creatable).toBe(true);
});
});
describe("the folder grid view", () => {
let gridViewProvider;
let listViewProvider;
let folderObject;
let addCallback;
let parentDiv;
let childDiv;
beforeEach(() => {
parentDiv = document.createElement("div");
childDiv = document.createElement("div");
parentDiv.appendChild(childDiv);
folderObject = {
identifier: {
namespace: 'test-namespace',
key: 'folder-object'
},
name: "A folder!",
type: "folder",
composition: [
{
namespace: 'test-namespace',
key: 'child-object-1'
}, {
namespace: 'test-namespace',
key: 'child-object-2'
}, {
namespace: 'test-namespace',
key: 'child-object-3'
}, {
namespace: 'test-namespace',
key: 'child-object-4'
}
]
};
gridViewProvider = openmct.objectViews.get(folderObject, [folderObject]).find((view) => view.key === 'grid');
listViewProvider = openmct.objectViews.get(folderObject, [folderObject]).find((view) => view.key === 'list-view');
const fakeCompositionCollection = jasmine.createSpyObj('compositionCollection', [
'on',
'load'
]);
fakeCompositionCollection.on.and.callFake((eventName, callback) => {
if (eventName === "add") {
addCallback = callback;
}
});
fakeCompositionCollection.load.and.callFake(() => {
folderObject.composition.forEach((identifier) => {
addCallback({
identifier,
type: "folder"
});
});
});
spyOn(openmct.composition, "get").and.returnValue(fakeCompositionCollection);
});
describe("the grid view", () => {
it("is installed by the plugin and is applicable to the folder type", () => {
expect(gridViewProvider).toBeDefined();
});
it("renders each item contained in the folder's composition", async () => {
let folderView = gridViewProvider.view(folderObject, [folderObject]);
folderView.show(childDiv, true);
await Vue.nextTick();
let children = parentDiv.getElementsByClassName("js-folder-child");
expect(children.length).toBe(folderObject.composition.length);
});
});
describe("the list view", () => {
it("installs a list view for the folder type", () => {
expect(listViewProvider).toBeDefined();
});
it("renders each item contained in the folder's composition", async () => {
let folderView = listViewProvider.view(folderObject, [folderObject]);
folderView.show(childDiv, true);
await Vue.nextTick();
let children = parentDiv.getElementsByClassName("js-folder-child");
expect(children.length).toBe(folderObject.composition.length);
});
});
});
});