diff --git a/platform/commonUI/edit/bundle.js b/platform/commonUI/edit/bundle.js index 2c5a79bda3..b81e057764 100644 --- a/platform/commonUI/edit/bundle.js +++ b/platform/commonUI/edit/bundle.js @@ -30,7 +30,7 @@ define([ "./src/actions/EditAction", "./src/actions/PropertiesAction", "./src/actions/RemoveAction", - "./src/actions/SaveAction", + "./src/actions/SaveAndStopEditingAction", "./src/actions/SaveAsAction", "./src/actions/CancelAction", "./src/policies/EditActionPolicy", @@ -69,7 +69,7 @@ define([ EditAction, PropertiesAction, RemoveAction, - SaveAction, + SaveAndStopEditingAction, SaveAsAction, CancelAction, EditActionPolicy, @@ -205,7 +205,7 @@ define([ { "key": "save", "category": "conclude-editing", - "implementation": SaveAction, + "implementation": SaveAndStopEditingAction, "name": "Save", "cssclass": "icon-save labeled", "description": "Save changes made to these objects.", diff --git a/platform/commonUI/edit/src/actions/SaveAndStopEditingAction.js b/platform/commonUI/edit/src/actions/SaveAndStopEditingAction.js new file mode 100644 index 0000000000..a6a1eb9e62 --- /dev/null +++ b/platform/commonUI/edit/src/actions/SaveAndStopEditingAction.js @@ -0,0 +1,73 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2016, 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( + ["./SaveAction"], + function (SaveAction) { + + /** + * The "Save and Stop Editing" action performs a [Save action]{@link SaveAction} + * on the object under edit followed by exiting the edit user interface. + * @constructor + * @implements {Action} + * @memberof platform/commonUI/edit + */ + function SaveAndStopEditingAction( + dialogService, + context + ) { + this.context = context; + this.domainObject = (context || {}).domainObject; + this.dialogService = dialogService; + } + + /** + * Trigger a save operation and exit edit mode. + * + * @returns {Promise} a promise that will be fulfilled when + * cancellation has completed + * @memberof platform/commonUI/edit.SaveAndStopEditingAction# + */ + SaveAndStopEditingAction.prototype.perform = function () { + var domainObject = this.domainObject, + saveAction = new SaveAction(this.dialogService, this.context); + + function closeEditor() { + return domainObject.getCapability("editor").cancel(); + } + + return saveAction.perform() + .then(closeEditor) + .catch(closeEditor); + }; + + /** + * Check if this action is applicable in a given context. + * This will ensure that a domain object is present in the context, + * and that this domain object is in Edit mode. + * @returns true if applicable + */ + SaveAndStopEditingAction.appliesTo = SaveAction.appliesTo; + + return SaveAndStopEditingAction; + } +); \ No newline at end of file diff --git a/platform/commonUI/edit/test/actions/SaveAndStopEditingActionSpec.js b/platform/commonUI/edit/test/actions/SaveAndStopEditingActionSpec.js new file mode 100644 index 0000000000..a5d14e3d6d --- /dev/null +++ b/platform/commonUI/edit/test/actions/SaveAndStopEditingActionSpec.js @@ -0,0 +1,118 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2016, 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/actions/SaveAndStopEditingAction"], + function (SaveAndStopEditingAction) { + + describe("The Save and Stop Editing action", function () { + + var mockDomainObject, + mockEditorCapability, + actionContext, + dialogService, + mockActionCapability, + capabilities = {}, + action; + + function mockPromise(value) { + return { + then: function (callback) { + return mockPromise(callback(value)); + }, + catch: function (callback) { + return mockPromise(callback(value)); + } + }; + } + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + "domainObject", + [ + "getCapability", + "hasCapability", + "getModel", + "getOriginalObject" + ] + ); + mockEditorCapability = jasmine.createSpyObj( + "editor", + ["save", "cancel", "isEditContextRoot"] + ); + mockActionCapability = jasmine.createSpyObj( + "actionCapability", + ["perform"] + ); + capabilities.editor = mockEditorCapability; + capabilities.action = mockActionCapability; + + actionContext = { + domainObject: mockDomainObject + }; + dialogService = jasmine.createSpyObj( + "dialogService", + ["showBlockingMessage"] + ); + + mockDomainObject.hasCapability.andReturn(true); + mockDomainObject.getCapability.andCallFake(function (capability) { + return capabilities[capability]; + }); + mockDomainObject.getModel.andReturn({ persisted: 0 }); + mockEditorCapability.save.andReturn(mockPromise(true)); + mockEditorCapability.isEditContextRoot.andReturn(true); + + action = new SaveAndStopEditingAction(dialogService, actionContext); + }); + + + it("only applies to domain object with an editor capability", function () { + expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(true); + expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor"); + + mockDomainObject.hasCapability.andReturn(false); + mockDomainObject.getCapability.andReturn(undefined); + expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false); + }); + + it("only applies to domain object that has already been persisted", function () { + mockDomainObject.getModel.andReturn({ persisted: undefined }); + expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false); + }); + + it("does not close the editor before completing the save", function () { + mockEditorCapability.save.andReturn(new Promise(function () { + })); + action.perform(); + expect(mockEditorCapability.save).toHaveBeenCalled(); + expect(mockEditorCapability.cancel).not.toHaveBeenCalled(); + }); + + it("closes the editor after saving", function () { + action.perform(); + expect(mockEditorCapability.save).toHaveBeenCalled(); + expect(mockEditorCapability.cancel).toHaveBeenCalled(); + }); + }); + } +); \ No newline at end of file