diff --git a/platform/commonUI/edit/src/actions/PropertiesAction.js b/platform/commonUI/edit/src/actions/PropertiesAction.js index fae55bee14..7d0e43ff77 100644 --- a/platform/commonUI/edit/src/actions/PropertiesAction.js +++ b/platform/commonUI/edit/src/actions/PropertiesAction.js @@ -80,18 +80,15 @@ define( * This will ensure that a domain object is present in the * context. */ - PropertiesAction.appliesTo = function (context) { + PropertiesAction.appliesTo = function (context, view, openmct) { - var domainObject = (context || {}).domainObject, - type = domainObject && domainObject.getCapability('type'), - creatable = type && type.hasFeature('creation'); + let domainObject = (context || {}).domainObject; - if (domainObject && domainObject.model && domainObject.model.locked) { + if (!domainObject || (domainObject.model && domainObject.model.locked)) { return false; } - // Only allow creatable types to be edited - return domainObject && creatable; + return openmct.objects.isPersistable(domainObject.id); }; return PropertiesAction; diff --git a/platform/commonUI/edit/test/actions/PropertiesActionSpec.js b/platform/commonUI/edit/test/actions/PropertiesActionSpec.js index fff5123f0b..aa167373f2 100644 --- a/platform/commonUI/edit/test/actions/PropertiesActionSpec.js +++ b/platform/commonUI/edit/test/actions/PropertiesActionSpec.js @@ -25,7 +25,7 @@ define( function (PropertiesAction) { describe("Properties action", function () { - var capabilities, model, object, context, input, dialogService, action; + var capabilities, model, object, context, input, dialogService, action, openmct; function mockPromise(value) { return { @@ -36,6 +36,11 @@ define( } beforeEach(function () { + openmct = { + objects: { + isPersistable: jasmine.createSpy('isPersistable') + } + }; capabilities = { type: { getProperties: function () { @@ -77,6 +82,8 @@ define( capabilities.type.hasFeature.and.returnValue(true); capabilities.mutation.and.returnValue(true); + openmct.objects.isPersistable.and.returnValue(true); + action = new PropertiesAction(dialogService, context); }); @@ -93,11 +100,11 @@ define( }); it("is only applicable when a domain object is in context", function () { - expect(PropertiesAction.appliesTo(context)).toBeTruthy(); - expect(PropertiesAction.appliesTo({})).toBeFalsy(); - // Make sure it checked for creatability - expect(capabilities.type.hasFeature).toHaveBeenCalledWith('creation'); + expect(PropertiesAction.appliesTo(context, undefined, openmct)).toBeTruthy(); + expect(PropertiesAction.appliesTo({}, undefined, openmct)).toBeFalsy(); + expect(openmct.objects.isPersistable).toHaveBeenCalled(); }); + }); } ); diff --git a/platform/entanglement/src/actions/SetPrimaryLocationAction.js b/platform/entanglement/src/actions/SetPrimaryLocationAction.js index f283fa96a8..a5c4a257da 100644 --- a/platform/entanglement/src/actions/SetPrimaryLocationAction.js +++ b/platform/entanglement/src/actions/SetPrimaryLocationAction.js @@ -47,10 +47,16 @@ define( ); }; - SetPrimaryLocationAction.appliesTo = function (context) { - var domainObject = context.domainObject; + SetPrimaryLocationAction.appliesTo = function (context, view, openmct) { + let domainObject = (context || {}).domainObject; - return domainObject && domainObject.hasCapability("location") + if (!domainObject || (domainObject.model && domainObject.model.locked)) { + return false; + } + + let isPersistable = openmct.objects.isPersistable(domainObject.id); + + return isPersistable && domainObject.hasCapability("location") && (domainObject.getModel().location === undefined); }; diff --git a/platform/entanglement/test/actions/SetPrimaryLocationActionSpec.js b/platform/entanglement/test/actions/SetPrimaryLocationActionSpec.js index 9ef6a170e9..317ceb7e3d 100644 --- a/platform/entanglement/test/actions/SetPrimaryLocationActionSpec.js +++ b/platform/entanglement/test/actions/SetPrimaryLocationActionSpec.js @@ -31,9 +31,15 @@ define( var testContext, testModel, testId, - mockLocationCapability; + mockLocationCapability, + openmct; beforeEach(function () { + openmct = { + objects: { + isPersistable: jasmine.createSpy('isPersistable') + } + }; testId = "some-id"; testModel = { name: "some name" }; @@ -42,6 +48,7 @@ define( ['setPrimaryLocation', 'getContextualLocation'] ); + openmct.objects.isPersistable.and.returnValue(true); mockLocationCapability.getContextualLocation.and.returnValue(testId); testContext = { @@ -55,16 +62,21 @@ define( }); it("is applicable to objects with no location specified", function () { - expect(SetPrimaryLocation.appliesTo(testContext)) + expect(SetPrimaryLocation.appliesTo(testContext, undefined, openmct)) .toBe(true); testContext.domainObject.getModel.and.returnValue({ location: "something", name: "some name" }); - expect(SetPrimaryLocation.appliesTo(testContext)) + expect(SetPrimaryLocation.appliesTo(testContext, undefined, openmct)) .toBe(false); }); + it("checks object persistability", function () { + SetPrimaryLocation.appliesTo(testContext, undefined, openmct); + expect(openmct.objects.isPersistable).toHaveBeenCalled(); + }); + it("sets the location contextually when performed", function () { new SetPrimaryLocation(testContext).perform(); expect(mockLocationCapability.setPrimaryLocation) diff --git a/platform/import-export/src/actions/ImportAsJSONAction.js b/platform/import-export/src/actions/ImportAsJSONAction.js index 5ab16f9f98..c510e605b7 100644 --- a/platform/import-export/src/actions/ImportAsJSONAction.js +++ b/platform/import-export/src/actions/ImportAsJSONAction.js @@ -221,15 +221,17 @@ define(['zepto', 'objectUtils'], function ($, objectUtils) { dialog = this.dialogService.showBlockingMessage(model); }; - ImportAsJSONAction.appliesTo = function (context) { - let domainObject = context.domainObject; + ImportAsJSONAction.appliesTo = function (context, view, openmct) { + let domainObject = (context || {}).domainObject; - if (domainObject && domainObject.model.locked) { + if (!domainObject || (domainObject.model && domainObject.model.locked)) { return false; } - return domainObject !== undefined - && domainObject.hasCapability("composition"); + let isPersistable = openmct.objects.isPersistable(domainObject.id); + let hasComposition = domainObject.hasCapability('composition'); + + return hasComposition && isPersistable; }; return ImportAsJSONAction; diff --git a/platform/import-export/test/actions/ImportAsJSONActionSpec.js b/platform/import-export/test/actions/ImportAsJSONActionSpec.js index 4e5d6acd6e..5ab03ec113 100644 --- a/platform/import-export/test/actions/ImportAsJSONActionSpec.js +++ b/platform/import-export/test/actions/ImportAsJSONActionSpec.js @@ -42,7 +42,6 @@ define( newObjects; beforeEach(function () { - uniqueId = 0; newObjects = []; openmct = { @@ -50,9 +49,11 @@ define( objects: { makeKeyString: function (identifier) { return identifier.key; - } + }, + isPersistable: jasmine.createSpy('isPersistable') } }; + openmct.objects.isPersistable.and.returnValue(true); mockInstantiate = jasmine.createSpy('instantiate').and.callFake( function (model, id) { var config = { @@ -121,9 +122,22 @@ define( var noCompDomainObject = domainObjectFactory(); context.domainObject = compDomainObject; - expect(ImportAsJSONAction.appliesTo(context)).toBe(true); + expect(ImportAsJSONAction.appliesTo(context, undefined, openmct)).toBe(true); context.domainObject = noCompDomainObject; - expect(ImportAsJSONAction.appliesTo(context)).toBe(false); + expect(ImportAsJSONAction.appliesTo(context, undefined, openmct)).toBe(false); + }); + + it("checks object persistability", function () { + var compDomainObject = domainObjectFactory({ + name: 'compObject', + model: { name: 'compObject'}, + capabilities: {"composition": compositionCapability} + }); + + context.domainObject = compDomainObject; + ImportAsJSONAction.appliesTo(context, undefined, openmct); + + expect(openmct.objects.isPersistable).toHaveBeenCalled(); }); it("displays error dialog on invalid file choice", function () { diff --git a/src/adapter/actions/LegacyContextMenuAction.js b/src/adapter/actions/LegacyContextMenuAction.js index 7b39179a12..eef1c93561 100644 --- a/src/adapter/actions/LegacyContextMenuAction.js +++ b/src/adapter/actions/LegacyContextMenuAction.js @@ -60,9 +60,10 @@ export default class LegacyContextMenuAction { appliesTo(objectPath) { let legacyObject = this.openmct.legacyObject(objectPath); + let view; return (this.LegacyAction.appliesTo === undefined - || this.LegacyAction.appliesTo({domainObject: legacyObject})) + || this.LegacyAction.appliesTo({domainObject: legacyObject}, view, this.openmct)) && !this.isBlacklisted(objectPath); } diff --git a/src/plugins/newFolderAction/newFolderAction.js b/src/plugins/newFolderAction/newFolderAction.js index 0430981372..ff7a24a228 100644 --- a/src/plugins/newFolderAction/newFolderAction.js +++ b/src/plugins/newFolderAction/newFolderAction.js @@ -83,7 +83,8 @@ export default class NewFolderAction { } appliesTo(objectPath) { let domainObject = objectPath[0]; + let isPersistable = this._openmct.objects.isPersistable(domainObject.identifier); - return domainObject.type === 'folder'; + return domainObject.type === 'folder' && isPersistable; } } diff --git a/src/plugins/newFolderAction/pluginSpec.js b/src/plugins/newFolderAction/pluginSpec.js index 923a5f7b51..7b6dad1940 100644 --- a/src/plugins/newFolderAction/pluginSpec.js +++ b/src/plugins/newFolderAction/pluginSpec.js @@ -78,6 +78,7 @@ describe("the plugin", () => { spyOn(openmct.$injector, 'get').and.returnValue(mockDialogService); spyOn(compositionAPI, 'get').and.returnValue(mockComposition); spyOn(openmct.objects, 'save').and.returnValue(Promise.resolve(true)); + spyOn(openmct.objects, 'isPersistable').and.returnValue(true); return newFolderAction.invoke(mockObjectPath); }); @@ -93,5 +94,11 @@ describe("the plugin", () => { it('adds new folder object to parent composition', () => { expect(mockComposition.add).toHaveBeenCalled(); }); + + it('checks if the domainObject is persistable', () => { + newFolderAction.appliesTo(mockObjectPath); + + expect(openmct.objects.isPersistable).toHaveBeenCalled(); + }); }); }); diff --git a/src/ui/layout/BrowseBar.vue b/src/ui/layout/BrowseBar.vue index df5287c82e..dd2c724402 100644 --- a/src/ui/layout/BrowseBar.vue +++ b/src/ui/layout/BrowseBar.vue @@ -20,8 +20,8 @@