mirror of
https://github.com/nasa/openmct.git
synced 2025-05-08 11:38:35 +00:00
Merge branch 'BogdanAlexandru-mct588comm'
This commit is contained in:
commit
c179d9e759
@ -64,7 +64,7 @@ define(
|
|||||||
var editing = currentObject.hasCapability('editor') &&
|
var editing = currentObject.hasCapability('editor') &&
|
||||||
currentObject.getCapability('editor').isEditContextRoot();
|
currentObject.getCapability('editor').isEditContextRoot();
|
||||||
|
|
||||||
return self.$q.when(editing && currentObject.getCapability("editor").cancel());
|
return self.$q.when(editing && currentObject.getCapability("editor").finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigate() {
|
function navigate() {
|
||||||
|
@ -61,7 +61,7 @@ define(
|
|||||||
|
|
||||||
capabilities.editor = jasmine.createSpyObj("editorCapability", [
|
capabilities.editor = jasmine.createSpyObj("editorCapability", [
|
||||||
"isEditContextRoot",
|
"isEditContextRoot",
|
||||||
"cancel"
|
"finish"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
mockNavigatedObject.getCapability.andCallFake(function (capability) {
|
mockNavigatedObject.getCapability.andCallFake(function (capability) {
|
||||||
@ -148,9 +148,9 @@ define(
|
|||||||
capabilities.editor.isEditContextRoot.andReturn(true);
|
capabilities.editor.isEditContextRoot.andReturn(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("cancels editing if in edit mode", function () {
|
it("finishes editing if in edit mode", function () {
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(capabilities.editor.cancel)
|
expect(capabilities.editor.finish)
|
||||||
.toHaveBeenCalled();
|
.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -31,6 +31,7 @@ define([
|
|||||||
"./src/actions/PropertiesAction",
|
"./src/actions/PropertiesAction",
|
||||||
"./src/actions/RemoveAction",
|
"./src/actions/RemoveAction",
|
||||||
"./src/actions/SaveAction",
|
"./src/actions/SaveAction",
|
||||||
|
"./src/actions/SaveAndStopEditingAction",
|
||||||
"./src/actions/SaveAsAction",
|
"./src/actions/SaveAsAction",
|
||||||
"./src/actions/CancelAction",
|
"./src/actions/CancelAction",
|
||||||
"./src/policies/EditActionPolicy",
|
"./src/policies/EditActionPolicy",
|
||||||
@ -70,6 +71,7 @@ define([
|
|||||||
PropertiesAction,
|
PropertiesAction,
|
||||||
RemoveAction,
|
RemoveAction,
|
||||||
SaveAction,
|
SaveAction,
|
||||||
|
SaveAndStopEditingAction,
|
||||||
SaveAsAction,
|
SaveAsAction,
|
||||||
CancelAction,
|
CancelAction,
|
||||||
EditActionPolicy,
|
EditActionPolicy,
|
||||||
@ -203,20 +205,30 @@ define([
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "save",
|
"key": "save-and-stop-editing",
|
||||||
"category": "conclude-editing",
|
"category": "save",
|
||||||
"implementation": SaveAction,
|
"implementation": SaveAndStopEditingAction,
|
||||||
"name": "Save",
|
"name": "Save and Finish Editing",
|
||||||
"cssclass": "icon-save labeled",
|
"cssclass": "icon-save labeled",
|
||||||
"description": "Save changes made to these objects.",
|
"description": "Save changes made to these objects.",
|
||||||
"depends": [
|
"depends": [
|
||||||
"dialogService"
|
"dialogService"
|
||||||
],
|
]
|
||||||
"priority": "mandatory"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "save",
|
"key": "save",
|
||||||
"category": "conclude-editing",
|
"category": "save",
|
||||||
|
"implementation": SaveAction,
|
||||||
|
"name": "Save and Continue Editing",
|
||||||
|
"cssclass": "icon-save labeled",
|
||||||
|
"description": "Save changes made to these objects.",
|
||||||
|
"depends": [
|
||||||
|
"dialogService"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "save-as",
|
||||||
|
"category": "save",
|
||||||
"implementation": SaveAsAction,
|
"implementation": SaveAsAction,
|
||||||
"name": "Save As...",
|
"name": "Save As...",
|
||||||
"cssclass": "icon-save labeled",
|
"cssclass": "icon-save labeled",
|
||||||
@ -225,7 +237,6 @@ define([
|
|||||||
"$injector",
|
"$injector",
|
||||||
"policyService",
|
"policyService",
|
||||||
"dialogService",
|
"dialogService",
|
||||||
"creationService",
|
|
||||||
"copyService"
|
"copyService"
|
||||||
],
|
],
|
||||||
"priority": "mandatory"
|
"priority": "mandatory"
|
||||||
|
@ -20,11 +20,32 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<span ng-controller="EditActionController">
|
<span ng-controller="EditActionController">
|
||||||
<span ng-repeat="currentAction in editActions">
|
<!-- If there's a single save action show a button, otherwise show a dropdown with all save actions. -->
|
||||||
|
<span ng-if="saveActions.length === 1">
|
||||||
|
<mct-control key="'button'"
|
||||||
|
structure="{
|
||||||
|
text: saveActions[0].getMetadata().name,
|
||||||
|
click: saveActions[0].perform,
|
||||||
|
cssclass: 'major ' + saveActions[0].getMetadata().cssclass
|
||||||
|
}">
|
||||||
|
</mct-control>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span ng-if="saveActions.length > 1">
|
||||||
|
<mct-control key="'menu-button'"
|
||||||
|
structure="{
|
||||||
|
options: saveActionsAsMenuOptions,
|
||||||
|
click: saveActionMenuClickHandler,
|
||||||
|
cssclass: 'btn-bar right icon-save no-label major'
|
||||||
|
}">
|
||||||
|
</mct-control>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span ng-repeat="currentAction in otherEditActions">
|
||||||
<a class='s-button {{currentAction.getMetadata().cssclass}}'
|
<a class='s-button {{currentAction.getMetadata().cssclass}}'
|
||||||
title='{{currentAction.getMetadata().name}}'
|
title='{{currentAction.getMetadata().name}}'
|
||||||
ng-click="currentAction.perform()"
|
ng-click="currentAction.perform()"
|
||||||
ng-class="{ major: $index === 0 }">
|
ng-class="{ major: $index === 0 && saveActions.length === 0 }">
|
||||||
<span class="title-label">{{currentAction.getMetadata().name}}</span>
|
<span class="title-label">{{currentAction.getMetadata().name}}</span>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -62,7 +62,7 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancel(allowed) {
|
function cancel(allowed) {
|
||||||
return allowed && domainObject.getCapability("editor").cancel();
|
return allowed && domainObject.getCapability("editor").finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Do navigation first in order to trigger unsaved changes dialog
|
//Do navigation first in order to trigger unsaved changes dialog
|
||||||
|
@ -25,9 +25,8 @@ define(
|
|||||||
function (SaveInProgressDialog) {
|
function (SaveInProgressDialog) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "Save" action; the action triggered by clicking Save from
|
* The "Save" action; it invokes object capabilities to persist
|
||||||
* Edit Mode. Exits the editing user interface and invokes object
|
* the changes that have been made.
|
||||||
* capabilities to persist the changes that have been made.
|
|
||||||
* @constructor
|
* @constructor
|
||||||
* @implements {Action}
|
* @implements {Action}
|
||||||
* @memberof platform/commonUI/edit
|
* @memberof platform/commonUI/edit
|
||||||
@ -41,7 +40,7 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save changes and conclude editing.
|
* Save changes.
|
||||||
*
|
*
|
||||||
* @returns {Promise} a promise that will be fulfilled when
|
* @returns {Promise} a promise that will be fulfilled when
|
||||||
* cancellation has completed
|
* cancellation has completed
|
||||||
@ -51,40 +50,22 @@ define(
|
|||||||
var domainObject = this.domainObject,
|
var domainObject = this.domainObject,
|
||||||
dialog = new SaveInProgressDialog(this.dialogService);
|
dialog = new SaveInProgressDialog(this.dialogService);
|
||||||
|
|
||||||
function resolveWith(object) {
|
|
||||||
return function () {
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoke any save behavior introduced by the editor capability;
|
// Invoke any save behavior introduced by the editor capability;
|
||||||
// this is introduced by EditableDomainObject which is
|
// this is introduced by EditableDomainObject which is
|
||||||
// used to insulate underlying objects from changes made
|
// used to insulate underlying objects from changes made
|
||||||
// during editing.
|
// during editing.
|
||||||
function doSave() {
|
function doSave() {
|
||||||
return domainObject.getCapability("editor").save()
|
return domainObject.getCapability("editor").save();
|
||||||
.then(resolveWith(domainObject));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard the current root view (which will be the editing
|
function hideBlockingDialog() {
|
||||||
// UI, which will have been pushed atop the Browse UI.)
|
|
||||||
function returnToBrowse(object) {
|
|
||||||
if (object) {
|
|
||||||
object.getCapability("action").perform("navigate");
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideBlockingDialog(object) {
|
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
return doSave()
|
return doSave()
|
||||||
.then(hideBlockingDialog)
|
.then(hideBlockingDialog)
|
||||||
.then(returnToBrowse)
|
|
||||||
.catch(hideBlockingDialog);
|
.catch(hideBlockingDialog);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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").finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
);
|
@ -42,7 +42,6 @@ define([
|
|||||||
$injector,
|
$injector,
|
||||||
policyService,
|
policyService,
|
||||||
dialogService,
|
dialogService,
|
||||||
creationService,
|
|
||||||
copyService,
|
copyService,
|
||||||
context
|
context
|
||||||
) {
|
) {
|
||||||
@ -52,7 +51,6 @@ define([
|
|||||||
};
|
};
|
||||||
this.policyService = policyService;
|
this.policyService = policyService;
|
||||||
this.dialogService = dialogService;
|
this.dialogService = dialogService;
|
||||||
this.creationService = creationService;
|
|
||||||
this.copyService = copyService;
|
this.copyService = copyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,11 +164,16 @@ define([
|
|||||||
.then(resolveWith(object));
|
.then(resolveWith(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
function commitEditingAfterClone(clonedObject) {
|
function saveAfterClone(clonedObject) {
|
||||||
return domainObject.getCapability("editor").save()
|
return domainObject.getCapability("editor").save()
|
||||||
.then(resolveWith(clonedObject));
|
.then(resolveWith(clonedObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function finishEditing(clonedObject) {
|
||||||
|
return domainObject.getCapability("editor").finish()
|
||||||
|
.then(resolveWith(clonedObject));
|
||||||
|
}
|
||||||
|
|
||||||
function onFailure() {
|
function onFailure() {
|
||||||
hideBlockingDialog();
|
hideBlockingDialog();
|
||||||
return false;
|
return false;
|
||||||
@ -182,7 +185,8 @@ define([
|
|||||||
.then(getParent)
|
.then(getParent)
|
||||||
.then(cloneIntoParent)
|
.then(cloneIntoParent)
|
||||||
.then(undirtyOriginals)
|
.then(undirtyOriginals)
|
||||||
.then(commitEditingAfterClone)
|
.then(saveAfterClone)
|
||||||
|
.then(finishEditing)
|
||||||
.then(hideBlockingDialog)
|
.then(hideBlockingDialog)
|
||||||
.catch(onFailure);
|
.catch(onFailure);
|
||||||
};
|
};
|
||||||
|
@ -28,8 +28,8 @@ define(
|
|||||||
* A capability that implements an editing 'session' for a domain
|
* A capability that implements an editing 'session' for a domain
|
||||||
* object. An editing session is initiated via a call to .edit().
|
* object. An editing session is initiated via a call to .edit().
|
||||||
* Once initiated, any persist operations will be queued pending a
|
* Once initiated, any persist operations will be queued pending a
|
||||||
* subsequent call to [.save()](@link #save) or [.cancel()](@link
|
* subsequent call to [.save()](@link #save) or [.finish()](@link
|
||||||
* #cancel).
|
* #finish).
|
||||||
* @param transactionService
|
* @param transactionService
|
||||||
* @param domainObject
|
* @param domainObject
|
||||||
* @constructor
|
* @constructor
|
||||||
@ -45,7 +45,7 @@ define(
|
|||||||
/**
|
/**
|
||||||
* Initiate an editing session. This will start a transaction during
|
* Initiate an editing session. This will start a transaction during
|
||||||
* which any persist operations will be deferred until either save()
|
* which any persist operations will be deferred until either save()
|
||||||
* or cancel() are called.
|
* or finish() are called.
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.edit = function () {
|
EditorCapability.prototype.edit = function () {
|
||||||
this.transactionService.startTransaction();
|
this.transactionService.startTransaction();
|
||||||
@ -81,25 +81,25 @@ define(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save any changes from this editing session. This will flush all
|
* Save any unsaved changes from this editing session. This will
|
||||||
* pending persists and end the current transaction
|
* end the current transaction and continue with a new one.
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.save = function () {
|
EditorCapability.prototype.save = function () {
|
||||||
var domainObject = this.domainObject;
|
var transactionService = this.transactionService;
|
||||||
return this.transactionService.commit().then(function () {
|
return transactionService.commit().then(function () {
|
||||||
domainObject.getCapability('status').set('editing', false);
|
transactionService.startTransaction();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorCapability.prototype.invoke = EditorCapability.prototype.edit;
|
EditorCapability.prototype.invoke = EditorCapability.prototype.edit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the current editing session. This will discard any pending
|
* Finish the current editing session. This will discard any pending
|
||||||
* persist operations
|
* persist operations
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.cancel = function () {
|
EditorCapability.prototype.finish = function () {
|
||||||
var domainObject = this.domainObject;
|
var domainObject = this.domainObject;
|
||||||
return this.transactionService.cancel().then(function () {
|
return this.transactionService.cancel().then(function () {
|
||||||
domainObject.getCapability("status").set("editing", false);
|
domainObject.getCapability("status").set("editing", false);
|
||||||
|
@ -27,7 +27,8 @@ define(
|
|||||||
[],
|
[],
|
||||||
function () {
|
function () {
|
||||||
|
|
||||||
var ACTION_CONTEXT = { category: 'conclude-editing' };
|
var SAVE_ACTION_CONTEXT = { category: 'save' };
|
||||||
|
var OTHERS_ACTION_CONTEXT = { category: 'conclude-editing' };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller which supplies action instances for Save/Cancel.
|
* Controller which supplies action instances for Save/Cancel.
|
||||||
@ -35,11 +36,30 @@ define(
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function EditActionController($scope) {
|
function EditActionController($scope) {
|
||||||
// Maintain all "conclude-editing" actions in the present
|
|
||||||
// context.
|
function actionToMenuOption(action) {
|
||||||
|
return {
|
||||||
|
key: action,
|
||||||
|
name: action.getMetadata().name,
|
||||||
|
cssclass: action.getMetadata().cssclass
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain all "conclude-editing" and "save" actions in the
|
||||||
|
// present context.
|
||||||
function updateActions() {
|
function updateActions() {
|
||||||
$scope.editActions = $scope.action ?
|
$scope.saveActions = $scope.action ?
|
||||||
$scope.action.getActions(ACTION_CONTEXT) :
|
$scope.action.getActions(SAVE_ACTION_CONTEXT) :
|
||||||
|
[];
|
||||||
|
|
||||||
|
$scope.saveActionsAsMenuOptions = $scope.saveActions.map(actionToMenuOption);
|
||||||
|
|
||||||
|
$scope.saveActionMenuClickHandler = function (clickedAction) {
|
||||||
|
clickedAction.perform();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.otherEditActions = $scope.action ?
|
||||||
|
$scope.action.getActions(OTHERS_ACTION_CONTEXT) :
|
||||||
[];
|
[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +67,17 @@ define(
|
|||||||
editAction,
|
editAction,
|
||||||
editorCapability;
|
editorCapability;
|
||||||
|
|
||||||
|
function closeEditor() {
|
||||||
|
return editorCapability.finish();
|
||||||
|
}
|
||||||
|
|
||||||
function onSave() {
|
function onSave() {
|
||||||
return editorCapability.save();
|
return editorCapability.save()
|
||||||
|
.then(closeEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancel() {
|
function onCancel() {
|
||||||
return editorCapability.cancel();
|
return closeEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
newModel.type = this.type.getKey();
|
newModel.type = this.type.getKey();
|
||||||
@ -85,9 +90,9 @@ define(
|
|||||||
if (editAction) {
|
if (editAction) {
|
||||||
return editAction.perform();
|
return editAction.perform();
|
||||||
} else if (editorCapability) {
|
} else if (editorCapability) {
|
||||||
//otherwise, use the save action
|
//otherwise, use the save as action
|
||||||
editorCapability.edit();
|
editorCapability.edit();
|
||||||
return newObject.getCapability("action").perform("save").then(onSave, onCancel);
|
return newObject.getCapability("action").perform("save-as").then(onSave, onCancel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ define(
|
|||||||
|
|
||||||
capabilities.editor = jasmine.createSpyObj(
|
capabilities.editor = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "cancel", "isEditContextRoot"]
|
["save", "finish", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
capabilities.action = jasmine.createSpyObj(
|
capabilities.action = jasmine.createSpyObj(
|
||||||
"actionCapability",
|
"actionCapability",
|
||||||
@ -105,7 +105,7 @@ define(
|
|||||||
return !!capabilities[name];
|
return !!capabilities[name];
|
||||||
});
|
});
|
||||||
|
|
||||||
capabilities.editor.cancel.andReturn(mockPromise(true));
|
capabilities.editor.finish.andReturn(mockPromise(true));
|
||||||
|
|
||||||
action = new CancelAction(actionContext);
|
action = new CancelAction(actionContext);
|
||||||
|
|
||||||
@ -130,8 +130,8 @@ define(
|
|||||||
capabilities.action.perform.andReturn(mockPromise(true));
|
capabilities.action.perform.andReturn(mockPromise(true));
|
||||||
action.perform();
|
action.perform();
|
||||||
|
|
||||||
// Should have called cancel
|
// Should have called finish
|
||||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||||
|
|
||||||
// Definitely shouldn't call save!
|
// Definitely shouldn't call save!
|
||||||
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
||||||
|
@ -58,7 +58,7 @@ define(
|
|||||||
);
|
);
|
||||||
mockEditor = jasmine.createSpyObj(
|
mockEditor = jasmine.createSpyObj(
|
||||||
"editorCapability",
|
"editorCapability",
|
||||||
["edit", "isEditContextRoot", "cancel"]
|
["edit", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
|
|
||||||
capabilities = {
|
capabilities = {
|
||||||
|
@ -56,7 +56,7 @@ define(
|
|||||||
);
|
);
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
mockEditorCapability = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "cancel", "isEditContextRoot"]
|
["save", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
mockActionCapability = jasmine.createSpyObj(
|
mockActionCapability = jasmine.createSpyObj(
|
||||||
"actionCapability",
|
"actionCapability",
|
||||||
@ -105,12 +105,6 @@ define(
|
|||||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("navigates to the object after saving",
|
|
||||||
function () {
|
|
||||||
action.perform();
|
|
||||||
expect(mockActionCapability.perform).toHaveBeenCalledWith("navigate");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("a blocking dialog", function () {
|
describe("a blocking dialog", function () {
|
||||||
var mockDialogHandle;
|
var mockDialogHandle;
|
||||||
|
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 () {
|
||||||
|
|
||||||
|
// Some mocks appear unused because the
|
||||||
|
// underlying SaveAction that this action
|
||||||
|
// depends on is not mocked, so we mock some
|
||||||
|
// of SaveAction's own dependencies to make
|
||||||
|
// it run.
|
||||||
|
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", "finish", "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.finish).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("closes the editor after saving", function () {
|
||||||
|
action.perform();
|
||||||
|
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||||
|
expect(mockEditorCapability.finish).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -19,7 +19,7 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*global describe,it,expect,beforeEach,jasmine*/
|
/*global describe,it,expect,beforeEach,jasmine,runs,waitsFor,spyOn*/
|
||||||
|
|
||||||
define(
|
define(
|
||||||
["../../src/actions/SaveAsAction"],
|
["../../src/actions/SaveAsAction"],
|
||||||
@ -33,7 +33,6 @@ define(
|
|||||||
mockDialogService,
|
mockDialogService,
|
||||||
mockCopyService,
|
mockCopyService,
|
||||||
mockParent,
|
mockParent,
|
||||||
mockUrlService,
|
|
||||||
actionContext,
|
actionContext,
|
||||||
capabilities = {},
|
capabilities = {},
|
||||||
action;
|
action;
|
||||||
@ -78,10 +77,10 @@ define(
|
|||||||
|
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
mockEditorCapability = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "cancel", "isEditContextRoot"]
|
["save", "finish", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
mockEditorCapability.cancel.andReturn(mockPromise(undefined));
|
|
||||||
mockEditorCapability.save.andReturn(mockPromise(true));
|
mockEditorCapability.save.andReturn(mockPromise(true));
|
||||||
|
mockEditorCapability.finish.andReturn(mockPromise(true));
|
||||||
mockEditorCapability.isEditContextRoot.andReturn(true);
|
mockEditorCapability.isEditContextRoot.andReturn(true);
|
||||||
capabilities.editor = mockEditorCapability;
|
capabilities.editor = mockEditorCapability;
|
||||||
|
|
||||||
@ -113,16 +112,11 @@ define(
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
mockUrlService = jasmine.createSpyObj(
|
|
||||||
"urlService",
|
|
||||||
["urlForLocation"]
|
|
||||||
);
|
|
||||||
|
|
||||||
actionContext = {
|
actionContext = {
|
||||||
domainObject: mockDomainObject
|
domainObject: mockDomainObject
|
||||||
};
|
};
|
||||||
|
|
||||||
action = new SaveAsAction(undefined, undefined, mockDialogService, undefined, mockCopyService, actionContext);
|
action = new SaveAsAction(undefined, undefined, mockDialogService, mockCopyService, actionContext);
|
||||||
|
|
||||||
spyOn(action, "getObjectService");
|
spyOn(action, "getObjectService");
|
||||||
action.getObjectService.andReturn(mockObjectService);
|
action.getObjectService.andReturn(mockObjectService);
|
||||||
@ -156,6 +150,28 @@ define(
|
|||||||
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
|
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses the editor capability to save the object", function () {
|
||||||
|
mockEditorCapability.save.andReturn(new Promise(function () {}));
|
||||||
|
runs(function () {
|
||||||
|
action.perform();
|
||||||
|
});
|
||||||
|
waitsFor(function () {
|
||||||
|
return mockEditorCapability.save.calls.length > 0;
|
||||||
|
}, "perform() should call EditorCapability.save");
|
||||||
|
runs(function () {
|
||||||
|
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses the editor capability to finish editing the object", function () {
|
||||||
|
runs(function () {
|
||||||
|
action.perform();
|
||||||
|
});
|
||||||
|
waitsFor(function () {
|
||||||
|
return mockEditorCapability.finish.calls.length > 0;
|
||||||
|
}, "perform() should call EditorCapability.finish");
|
||||||
|
});
|
||||||
|
|
||||||
it("returns to browse after save", function () {
|
it("returns to browse after save", function () {
|
||||||
spyOn(action, "save");
|
spyOn(action, "save");
|
||||||
action.save.andReturn(mockPromise(mockDomainObject));
|
action.save.andReturn(mockPromise(mockDomainObject));
|
||||||
|
@ -134,15 +134,15 @@ define(
|
|||||||
it("commits the transaction", function () {
|
it("commits the transaction", function () {
|
||||||
expect(mockTransactionService.commit).toHaveBeenCalled();
|
expect(mockTransactionService.commit).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
it("resets the edit state", function () {
|
it("begins a new transaction", function () {
|
||||||
expect(mockStatusCapability.set).toHaveBeenCalledWith('editing', false);
|
expect(mockTransactionService.startTransaction).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("cancel", function () {
|
describe("finish", function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
capability.edit();
|
capability.edit();
|
||||||
capability.cancel();
|
capability.finish();
|
||||||
});
|
});
|
||||||
it("cancels the transaction", function () {
|
it("cancels the transaction", function () {
|
||||||
expect(mockTransactionService.cancel).toHaveBeenCalled();
|
expect(mockTransactionService.cancel).toHaveBeenCalled();
|
||||||
@ -158,7 +158,7 @@ define(
|
|||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockDomainObject.getModel.andReturn(model);
|
mockDomainObject.getModel.andReturn(model);
|
||||||
capability.edit();
|
capability.edit();
|
||||||
capability.cancel();
|
capability.finish();
|
||||||
});
|
});
|
||||||
it("returns true if the object has been modified since it" +
|
it("returns true if the object has been modified since it" +
|
||||||
" was last persisted", function () {
|
" was last persisted", function () {
|
||||||
|
@ -19,22 +19,51 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
/*global describe,it,expect,beforeEach,jasmine*/
|
||||||
|
|
||||||
define(
|
define(
|
||||||
["../../src/controllers/EditActionController"],
|
["../../src/controllers/EditActionController"],
|
||||||
function (EditActionController) {
|
function (EditActionController) {
|
||||||
|
|
||||||
describe("The Edit Action controller", function () {
|
describe("The Edit Action controller", function () {
|
||||||
|
var mockSaveActionMetadata = {
|
||||||
|
name: "mocked-save-action",
|
||||||
|
cssclass: "mocked-save-action-css"
|
||||||
|
};
|
||||||
|
|
||||||
|
function fakeGetActions(actionContext) {
|
||||||
|
if (actionContext.category === "save") {
|
||||||
|
var mockedSaveActions = [
|
||||||
|
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"]),
|
||||||
|
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"])
|
||||||
|
];
|
||||||
|
mockedSaveActions.forEach(function (action) {
|
||||||
|
action.getMetadata.andReturn(mockSaveActionMetadata);
|
||||||
|
});
|
||||||
|
return mockedSaveActions;
|
||||||
|
} else if (actionContext.category === "conclude-editing") {
|
||||||
|
return ["a", "b", "c"];
|
||||||
|
} else {
|
||||||
|
throw "EditActionController uses a context that's not covered by tests.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var mockScope,
|
var mockScope,
|
||||||
mockActions,
|
mockActions,
|
||||||
controller;
|
controller;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
||||||
|
mockActions.getActions.andCallFake(fakeGetActions);
|
||||||
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
||||||
|
mockScope.action = mockActions;
|
||||||
controller = new EditActionController(mockScope);
|
controller = new EditActionController(mockScope);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function makeControllerUpdateActions() {
|
||||||
|
mockScope.$watch.mostRecentCall.args[1]();
|
||||||
|
}
|
||||||
|
|
||||||
it("watches scope that may change applicable actions", function () {
|
it("watches scope that may change applicable actions", function () {
|
||||||
// The action capability
|
// The action capability
|
||||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||||
@ -43,16 +72,34 @@ define(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("populates the scope with grouped and ungrouped actions", function () {
|
it("populates the scope with 'save' actions", function () {
|
||||||
mockScope.action = mockActions;
|
makeControllerUpdateActions();
|
||||||
|
expect(mockScope.saveActions.length).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
mockActions.getActions.andReturn(["a", "b", "c"]);
|
it("converts 'save' actions to their menu counterparts", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
var menuOptions = mockScope.saveActionsAsMenuOptions;
|
||||||
|
|
||||||
// Call the watch
|
expect(menuOptions.length).toEqual(2);
|
||||||
mockScope.$watch.mostRecentCall.args[1]();
|
expect(menuOptions[0].key).toEqual(mockScope.saveActions[0]);
|
||||||
|
expect(menuOptions[1].key).toEqual(mockScope.saveActions[1]);
|
||||||
|
menuOptions.forEach(function (option) {
|
||||||
|
expect(option.name).toEqual(mockSaveActionMetadata.name);
|
||||||
|
expect(option.cssclass).toEqual(mockSaveActionMetadata.cssclass);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Should have grouped and ungrouped actions in scope now
|
it("uses a click handler to perform the clicked action", function () {
|
||||||
expect(mockScope.editActions.length).toEqual(3);
|
makeControllerUpdateActions();
|
||||||
|
var sampleSaveAction = mockScope.saveActions[0];
|
||||||
|
mockScope.saveActionMenuClickHandler(sampleSaveAction);
|
||||||
|
expect(sampleSaveAction.perform).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("populates the scope with other editing actions", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
expect(mockScope.otherEditActions).toEqual(["a", "b", "c"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ define(
|
|||||||
[
|
[
|
||||||
"edit",
|
"edit",
|
||||||
"save",
|
"save",
|
||||||
"cancel"
|
"finish"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -142,6 +142,7 @@ define(
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("the perform function", function () {
|
describe("the perform function", function () {
|
||||||
|
var promise = jasmine.createSpyObj("promise", ["then"]);
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
capabilities.action.getActions.andReturn([mockEditAction]);
|
capabilities.action.getActions.andReturn([mockEditAction]);
|
||||||
});
|
});
|
||||||
@ -156,19 +157,20 @@ define(
|
|||||||
expect(mockEditAction.perform).toHaveBeenCalled();
|
expect(mockEditAction.perform).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses the save action if object does not have an edit action" +
|
it("uses the save-as action if object does not have an edit action" +
|
||||||
" available", function () {
|
" available", function () {
|
||||||
capabilities.action.getActions.andReturn([]);
|
capabilities.action.getActions.andReturn([]);
|
||||||
capabilities.action.perform.andReturn(mockPromise(undefined));
|
capabilities.action.perform.andReturn(mockPromise(undefined));
|
||||||
|
capabilities.editor.save.andReturn(promise);
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(capabilities.action.perform).toHaveBeenCalledWith("save");
|
expect(capabilities.action.perform).toHaveBeenCalledWith("save-as");
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("uses to editor capability", function () {
|
describe("uses to editor capability", function () {
|
||||||
var promise = jasmine.createSpyObj("promise", ["then"]);
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
capabilities.action.getActions.andReturn([]);
|
capabilities.action.getActions.andReturn([]);
|
||||||
capabilities.action.perform.andReturn(promise);
|
capabilities.action.perform.andReturn(promise);
|
||||||
|
capabilities.editor.save.andReturn(promise);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("to save the edit if user saves dialog", function () {
|
it("to save the edit if user saves dialog", function () {
|
||||||
@ -178,10 +180,10 @@ define(
|
|||||||
expect(capabilities.editor.save).toHaveBeenCalled();
|
expect(capabilities.editor.save).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("to cancel the edit if user cancels dialog", function () {
|
it("to finish the edit if user cancels dialog", function () {
|
||||||
action.perform();
|
action.perform();
|
||||||
promise.then.mostRecentCall.args[1]();
|
promise.then.mostRecentCall.args[1]();
|
||||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user