Merge pull request #1056 from nasa/blocking-save-dialog

[Save] Show blocking dialog
This commit is contained in:
Victor Woeltjen 2016-06-26 11:07:03 -07:00 committed by GitHub
commit 736cba76bb
6 changed files with 107 additions and 14 deletions

View File

@ -206,7 +206,9 @@ define([
"implementation": SaveAction, "implementation": SaveAction,
"name": "Save", "name": "Save",
"description": "Save changes made to these objects.", "description": "Save changes made to these objects.",
"depends": [], "depends": [
"dialogService"
],
"priority": "mandatory" "priority": "mandatory"
}, },
{ {

View File

@ -21,8 +21,8 @@
*****************************************************************************/ *****************************************************************************/
define( define(
[], ['./SaveInProgressDialog'],
function () { function (SaveInProgressDialog) {
/** /**
* The "Save" action; the action triggered by clicking Save from * The "Save" action; the action triggered by clicking Save from
@ -33,9 +33,11 @@ define(
* @memberof platform/commonUI/edit * @memberof platform/commonUI/edit
*/ */
function SaveAction( function SaveAction(
dialogService,
context context
) { ) {
this.domainObject = (context || {}).domainObject; this.domainObject = (context || {}).domainObject;
this.dialogService = dialogService;
} }
/** /**
@ -46,7 +48,8 @@ define(
* @memberof platform/commonUI/edit.SaveAction# * @memberof platform/commonUI/edit.SaveAction#
*/ */
SaveAction.prototype.perform = function () { SaveAction.prototype.perform = function () {
var domainObject = this.domainObject; var domainObject = this.domainObject,
dialog = new SaveInProgressDialog(this.dialogService);
function resolveWith(object) { function resolveWith(object) {
return function () { return function () {
@ -72,8 +75,17 @@ define(
return object; return object;
} }
//return doSave().then(returnToBrowse); function hideBlockingDialog(object) {
return doSave().then(returnToBrowse); dialog.hide();
return object;
}
dialog.show();
return doSave()
.then(hideBlockingDialog)
.then(returnToBrowse)
.catch(hideBlockingDialog);
}; };
/** /**

View File

@ -21,9 +21,14 @@
*****************************************************************************/ *****************************************************************************/
define( define([
['../creation/CreateWizard'], '../creation/CreateWizard',
function (CreateWizard) { './SaveInProgressDialog'
],
function (
CreateWizard,
SaveInProgressDialog
) {
/** /**
* The "Save" action; the action triggered by clicking Save from * The "Save" action; the action triggered by clicking Save from
@ -105,7 +110,8 @@ define(
SaveAsAction.prototype.save = function () { SaveAsAction.prototype.save = function () {
var self = this, var self = this,
domainObject = this.domainObject, domainObject = this.domainObject,
copyService = this.copyService; copyService = this.copyService,
dialog = new SaveInProgressDialog(this.dialogService);
function doWizardSave(parent) { function doWizardSave(parent) {
var wizard = self.createWizard(parent); var wizard = self.createWizard(parent);
@ -116,6 +122,16 @@ define(
).then(wizard.populateObjectFromInput.bind(wizard)); ).then(wizard.populateObjectFromInput.bind(wizard));
} }
function showBlockingDialog(object) {
dialog.show();
return object;
}
function hideBlockingDialog(object) {
dialog.hide();
return object;
}
function fetchObject(objectId) { function fetchObject(objectId) {
return self.getObjectService().getObjects([objectId]).then(function (objects) { return self.getObjectService().getObjects([objectId]).then(function (objects) {
return objects[objectId]; return objects[objectId];
@ -140,14 +156,22 @@ define(
.then(resolveWith(clonedObject)); .then(resolveWith(clonedObject));
} }
function onFailure() {
hideBlockingDialog();
return false;
}
return getParent(domainObject) return getParent(domainObject)
.then(doWizardSave) .then(doWizardSave)
.then(showBlockingDialog)
.then(getParent) .then(getParent)
.then(cloneIntoParent) .then(cloneIntoParent)
.then(commitEditingAfterClone) .then(commitEditingAfterClone)
.catch(resolveWith(false)); .then(hideBlockingDialog)
.catch(onFailure);
}; };
/** /**
* Check if this action is applicable in a given context. * Check if this action is applicable in a given context.
* This will ensure that a domain object is present in the context, * This will ensure that a domain object is present in the context,

View File

@ -0,0 +1,20 @@
define([], function () {
function SaveInProgressDialog(dialogService) {
this.dialogService = dialogService;
}
SaveInProgressDialog.prototype.show = function () {
this.dialogService.showBlockingMessage({
title: "Saving...",
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
unknownProgress: true,
severity: "info"
});
};
SaveInProgressDialog.prototype.hide = function () {
this.dialogService.dismiss();
};
return SaveInProgressDialog;
});

View File

@ -28,6 +28,7 @@ define(
var mockDomainObject, var mockDomainObject,
mockEditorCapability, mockEditorCapability,
actionContext, actionContext,
dialogService,
mockActionCapability, mockActionCapability,
capabilities = {}, capabilities = {},
action; action;
@ -36,6 +37,9 @@ define(
return { return {
then: function (callback) { then: function (callback) {
return mockPromise(callback(value)); return mockPromise(callback(value));
},
catch: function (callback) {
return mockPromise(callback(value));
} }
}; };
} }
@ -64,6 +68,10 @@ define(
actionContext = { actionContext = {
domainObject: mockDomainObject domainObject: mockDomainObject
}; };
dialogService = jasmine.createSpyObj(
"dialogService",
["showBlockingMessage", "dismiss"]
);
mockDomainObject.hasCapability.andReturn(true); mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andCallFake(function (capability) { mockDomainObject.getCapability.andCallFake(function (capability) {
@ -73,8 +81,7 @@ define(
mockEditorCapability.save.andReturn(mockPromise(true)); mockEditorCapability.save.andReturn(mockPromise(true));
mockEditorCapability.isEditContextRoot.andReturn(true); mockEditorCapability.isEditContextRoot.andReturn(true);
action = new SaveAction(actionContext); action = new SaveAction(dialogService, actionContext);
}); });
it("only applies to domain object with an editor capability", function () { it("only applies to domain object with an editor capability", function () {
@ -104,6 +111,19 @@ define(
expect(mockActionCapability.perform).toHaveBeenCalledWith("navigate"); expect(mockActionCapability.perform).toHaveBeenCalledWith("navigate");
}); });
it("shows a dialog while saving", function () {
mockEditorCapability.save.andReturn(new Promise(function () {}));
action.perform();
expect(dialogService.showBlockingMessage).toHaveBeenCalled();
expect(dialogService.dismiss).not.toHaveBeenCalled();
});
it("hides a dialog when saving is complete", function () {
action.perform();
expect(dialogService.showBlockingMessage).toHaveBeenCalled();
expect(dialogService.dismiss).toHaveBeenCalled();
});
}); });
} }
); );

View File

@ -100,7 +100,9 @@ define(
mockDialogService = jasmine.createSpyObj( mockDialogService = jasmine.createSpyObj(
"dialogService", "dialogService",
[ [
"getUserInput" "getUserInput",
"showBlockingMessage",
"dismiss"
] ]
); );
mockDialogService.getUserInput.andReturn(mockPromise(undefined)); mockDialogService.getUserInput.andReturn(mockPromise(undefined));
@ -169,6 +171,19 @@ define(
expect(mockDialogService.getUserInput).toHaveBeenCalled(); expect(mockDialogService.getUserInput).toHaveBeenCalled();
}); });
it("shows a blocking dialog while waiting for save", function () {
mockEditorCapability.save.andReturn(new Promise(function () {}));
action.perform();
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
expect(mockDialogService.dismiss).not.toHaveBeenCalled();
});
it("hides the blocking dialog after saving", function () {
action.perform();
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
expect(mockDialogService.dismiss).toHaveBeenCalled();
});
}); });
} }
); );