diff --git a/src/MCT.js b/src/MCT.js index 7168bfb2cb..e83cf89fb0 100644 --- a/src/MCT.js +++ b/src/MCT.js @@ -269,7 +269,6 @@ define([ this.install(this.plugins.ViewDatumAction()); this.install(this.plugins.ViewLargeAction()); this.install(this.plugins.ObjectInterceptors()); - this.install(this.plugins.NonEditableFolder()); this.install(this.plugins.DeviceClassifier()); this.install(this.plugins.UserIndicator()); } diff --git a/src/plugins/condition/components/inspector/StylesView.vue b/src/plugins/condition/components/inspector/StylesView.vue index 1975e5652c..9e0d8f9d4e 100644 --- a/src/plugins/condition/components/inspector/StylesView.vue +++ b/src/plugins/condition/components/inspector/StylesView.vue @@ -325,16 +325,7 @@ export default { return item && (item.type === type); }, canPersistObject(item) { - // for now the only way to tell if an object can be persisted is if it is creatable. - let creatable = false; - if (item) { - const type = this.openmct.types.get(item.type); - if (type && type.definition) { - creatable = (type.definition.creatable !== undefined && (type.definition.creatable === 'true' || type.definition.creatable === true)); - } - } - - return creatable; + return this.openmct.objects.isPersistable(item.identifier); }, hasConditionalStyle(domainObject, layoutItem) { const id = layoutItem ? layoutItem.id : undefined; diff --git a/src/plugins/duplicate/DuplicateAction.js b/src/plugins/duplicate/DuplicateAction.js index e0932af054..7181c990cf 100644 --- a/src/plugins/duplicate/DuplicateAction.js +++ b/src/plugins/duplicate/DuplicateAction.js @@ -97,13 +97,16 @@ export default class DuplicateAction { validate(currentParent) { return (data) => { - const parentCandidatePath = data.value; - const parentCandidate = parentCandidatePath[0]; + const parentCandidate = data.value[0]; let currentParentKeystring = this.openmct.objects.makeKeyString(currentParent.identifier); let parentCandidateKeystring = this.openmct.objects.makeKeyString(parentCandidate.identifier); let objectKeystring = this.openmct.objects.makeKeyString(this.object.identifier); + if (!this.openmct.objects.isPersistable(parentCandidate.identifier)) { + return false; + } + if (!parentCandidateKeystring || !currentParentKeystring) { return false; } @@ -122,13 +125,14 @@ export default class DuplicateAction { } appliesTo(objectPath) { - 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; + const parent = objectPath[1]; + const parentType = parent && this.openmct.types.get(parent.type); + const child = objectPath[0]; + const childType = child && this.openmct.types.get(child.type); + const locked = child.locked ? child.locked : parent && parent.locked; + const isPersistable = this.openmct.objects.isPersistable(child.identifier); - if (locked) { + if (locked || !isPersistable) { return false; } diff --git a/src/plugins/exportAsJSONAction/ExportAsJSONAction.js b/src/plugins/exportAsJSONAction/ExportAsJSONAction.js index 54d6b51edb..ba2f665da3 100644 --- a/src/plugins/exportAsJSONAction/ExportAsJSONAction.js +++ b/src/plugins/exportAsJSONAction/ExportAsJSONAction.js @@ -52,7 +52,7 @@ export default class ExportAsJSONAction { appliesTo(objectPath) { let domainObject = objectPath[0]; - return this._isCreatable(domainObject); + return this._isCreatableAndPersistable(domainObject); } /** * @@ -80,10 +80,11 @@ export default class ExportAsJSONAction { * @param {object} domainObject * @returns {boolean} */ - _isCreatable(domainObject) { + _isCreatableAndPersistable(domainObject) { const type = this.openmct.types.get(domainObject.type); + const isPersistable = this.openmct.objects.isPersistable(domainObject.identifier); - return type && type.definition.creatable; + return type && type.definition.creatable && isPersistable; } /** * @private @@ -170,7 +171,7 @@ export default class ExportAsJSONAction { .then((children) => { children.forEach((child, index) => { // Only export if object is creatable - if (this._isCreatable(child)) { + if (this._isCreatableAndPersistable(child)) { // Prevents infinite export of self-contained objs if (!Object.prototype.hasOwnProperty.call(this.tree, this._getId(child))) { // If object is a link to something absent from diff --git a/src/plugins/exportAsJSONAction/ExportAsJSONActionSpec.js b/src/plugins/exportAsJSONAction/ExportAsJSONActionSpec.js index 5499430709..b55feb25af 100644 --- a/src/plugins/exportAsJSONAction/ExportAsJSONActionSpec.js +++ b/src/plugins/exportAsJSONAction/ExportAsJSONActionSpec.js @@ -27,6 +27,10 @@ describe('Export as JSON plugin', () => { it('ExportAsJSONAction applies to folder', () => { domainObject = { + identifier: { + key: 'export-testing', + namespace: '' + }, composition: [], location: 'mine', modified: 1640115501237, @@ -40,6 +44,10 @@ describe('Export as JSON plugin', () => { it('ExportAsJSONAction applies to telemetry.plot.overlay', () => { domainObject = { + identifier: { + key: 'export-testing', + namespace: '' + }, composition: [], location: 'mine', modified: 1640115501237, @@ -53,6 +61,10 @@ describe('Export as JSON plugin', () => { it('ExportAsJSONAction applies to telemetry.plot.stacked', () => { domainObject = { + identifier: { + key: 'export-testing', + namespace: '' + }, composition: [], location: 'mine', modified: 1640115501237, @@ -64,16 +76,24 @@ describe('Export as JSON plugin', () => { expect(exportAsJSONAction.appliesTo([domainObject])).toEqual(true); }); - it('ExportAsJSONAction applies does not applies to non-creatable objects', () => { + it('ExportAsJSONAction does not applie to non-persistable objects', () => { domainObject = { + identifier: { + key: 'export-testing', + namespace: '' + }, composition: [], location: 'mine', modified: 1640115501237, name: 'Non Editable Folder', persisted: 1640115501237, - type: 'noneditable.folder' + type: 'folder' }; + spyOn(openmct.objects, 'getProvider').and.callFake(() => { + return { get: () => domainObject }; + }); + expect(exportAsJSONAction.appliesTo([domainObject])).toEqual(false); }); diff --git a/src/plugins/formActions/CreateWizard.js b/src/plugins/formActions/CreateWizard.js index 3705ae5fb5..8921a100ba 100644 --- a/src/plugins/formActions/CreateWizard.js +++ b/src/plugins/formActions/CreateWizard.js @@ -101,7 +101,10 @@ export default class CreateWizard { // Ensure there is always a 'save in' section if (includeLocation) { function validateLocation(data) { - return self.openmct.composition.checkPolicy(data.value[0], domainObject); + const policyCheck = self.openmct.composition.checkPolicy(data.value[0], domainObject); + const parentIsPersistable = self.openmct.objects.isPersistable(data.value[0].identifier); + + return policyCheck && parentIsPersistable; } sections.push({ diff --git a/src/plugins/linkAction/LinkAction.js b/src/plugins/linkAction/LinkAction.js index e4f4c8b47a..4c796e2343 100644 --- a/src/plugins/linkAction/LinkAction.js +++ b/src/plugins/linkAction/LinkAction.js @@ -33,10 +33,7 @@ export default class LinkAction { } appliesTo(objectPath) { - let domainObject = objectPath[0]; - let type = domainObject && this.openmct.types.get(domainObject.type); - - return type && type.definition.creatable; + return true; // link away! } invoke(objectPath) { @@ -77,6 +74,7 @@ export default class LinkAction { { name: "location", control: "locator", + parent: parentDomainObject, required: true, validate: this.validate(parentDomainObject), key: 'location' @@ -97,6 +95,10 @@ export default class LinkAction { const parentCandidateKeystring = this.openmct.objects.makeKeyString(parentCandidate.identifier); const objectKeystring = this.openmct.objects.makeKeyString(this.object.identifier); + if (!this.openmct.objects.isPersistable(parentCandidate.identifier)) { + return false; + } + if (!parentCandidateKeystring || !currentParentKeystring) { return false; } diff --git a/src/plugins/move/MoveAction.js b/src/plugins/move/MoveAction.js index 0e7e4c9092..d9a4d144ea 100644 --- a/src/plugins/move/MoveAction.js +++ b/src/plugins/move/MoveAction.js @@ -126,6 +126,7 @@ export default class MoveAction { { name: "Location", control: "locator", + parent: parentDomainObject, required: true, validate: this.validate(parentDomainObject), key: 'location' @@ -144,6 +145,10 @@ export default class MoveAction { const parentCandidatePath = data.value; const parentCandidate = parentCandidatePath[0]; + if (!this.openmct.objects.isPersistable(parentCandidate.identifier)) { + return false; + } + let currentParentKeystring = this.openmct.objects.makeKeyString(currentParent.identifier); let parentCandidateKeystring = this.openmct.objects.makeKeyString(parentCandidate.identifier); let objectKeystring = this.openmct.objects.makeKeyString(this.object.identifier); @@ -174,8 +179,9 @@ export default class MoveAction { let parentType = parent && this.openmct.types.get(parent.type); let child = objectPath[0]; let childType = child && this.openmct.types.get(child.type); + let isPersistable = this.openmct.objects.isPersistable(child.identifier); - if (child.locked || (parent && parent.locked)) { + if (child.locked || (parent && parent.locked) || !isPersistable) { return false; } diff --git a/src/plugins/nonEditableFolder/plugin.js b/src/plugins/nonEditableFolder/plugin.js deleted file mode 100644 index a8c0079fc3..0000000000 --- a/src/plugins/nonEditableFolder/plugin.js +++ /dev/null @@ -1,33 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2022, 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 () { - return function (openmct) { - openmct.types.addType("noneditable.folder", { - name: "Non-Editable Folder", - key: "noneditable.folder", - description: "Create folders to organize other objects or links to objects without the ability to edit it's properties.", - cssClass: "icon-folder", - creatable: false - }); - }; -} diff --git a/src/plugins/nonEditableFolder/pluginSpec.js b/src/plugins/nonEditableFolder/pluginSpec.js deleted file mode 100644 index 204061e8c6..0000000000 --- a/src/plugins/nonEditableFolder/pluginSpec.js +++ /dev/null @@ -1,50 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2022, 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'; - -describe("the plugin", () => { - const NON_EDITABLE_FOLDER_KEY = 'noneditable.folder'; - let openmct; - - beforeEach((done) => { - openmct = createOpenMct(); - openmct.install(openmct.plugins.NonEditableFolder()); - - openmct.on('start', done); - openmct.startHeadless(); - }); - - afterEach(() => { - return resetApplicationState(openmct); - }); - - it('adds the new non-editable folder type', () => { - const type = openmct.types.get(NON_EDITABLE_FOLDER_KEY); - - expect(type).toBeDefined(); - expect(type.definition.creatable).toBeFalse(); - }); - -}); diff --git a/src/plugins/plugins.js b/src/plugins/plugins.js index 1eda001611..4376222a70 100644 --- a/src/plugins/plugins.js +++ b/src/plugins/plugins.js @@ -61,7 +61,6 @@ define([ './URLTimeSettingsSynchronizer/plugin', './notificationIndicator/plugin', './newFolderAction/plugin', - './nonEditableFolder/plugin', './persistence/couch/plugin', './defaultRootName/plugin', './plan/plugin', @@ -119,7 +118,6 @@ define([ URLTimeSettingsSynchronizer, NotificationIndicator, NewFolderAction, - NonEditableFolder, CouchDBPlugin, DefaultRootName, PlanLayout, @@ -197,7 +195,6 @@ define([ plugins.URLTimeSettingsSynchronizer = URLTimeSettingsSynchronizer.default; plugins.NotificationIndicator = NotificationIndicator.default; plugins.NewFolderAction = NewFolderAction.default; - plugins.NonEditableFolder = NonEditableFolder.default; plugins.ISOTimeFormat = ISOTimeFormat.default; plugins.DefaultRootName = DefaultRootName.default; plugins.PlanLayout = PlanLayout.default; diff --git a/src/plugins/remove/RemoveAction.js b/src/plugins/remove/RemoveAction.js index 779bb1b8f4..6f208365eb 100644 --- a/src/plugins/remove/RemoveAction.js +++ b/src/plugins/remove/RemoveAction.js @@ -106,6 +106,11 @@ export default class RemoveAction { let child = objectPath[0]; let locked = child.locked ? child.locked : parent && parent.locked; let isEditing = this.openmct.editor.isEditing(); + let isPersistable = this.openmct.objects.isPersistable(child.identifier); + + if (locked || !isPersistable) { + return false; + } if (isEditing) { let currentItemInView = this.openmct.router.path[0]; @@ -116,10 +121,6 @@ export default class RemoveAction { } } - if (locked) { - return false; - } - return parentType && parentType.definition.creatable && Array.isArray(parent.composition); diff --git a/src/ui/layout/mct-tree.vue b/src/ui/layout/mct-tree.vue index 5475b64393..d78a7b8a19 100644 --- a/src/ui/layout/mct-tree.vue +++ b/src/ui/layout/mct-tree.vue @@ -258,10 +258,12 @@ export default { if (!this.isSelectorTree) { await this.syncTreeOpenItems(); } else { - const objectPath = await this.openmct.objects.getOriginalPath(this.initialSelection.identifier); - const navigationPath = this.buildNavigationPath(objectPath); + if (this.initialSelection.identifier) { + const objectPath = await this.openmct.objects.getOriginalPath(this.initialSelection.identifier); + const navigationPath = this.buildNavigationPath(objectPath); - this.openAndScrollTo(navigationPath); + this.openAndScrollTo(navigationPath); + } } }, created() {