Refactoring to use promises notifications

This commit is contained in:
Andrew Henry 2015-11-03 21:06:00 -08:00
parent bd1c3cb7da
commit fa7131ad5c
2 changed files with 65 additions and 22 deletions

View File

@ -26,6 +26,20 @@ define(
function (AbstractComposeAction) { function (AbstractComposeAction) {
"use strict"; "use strict";
/*
function CopyAction(locationService, copyService, context) {
return new AbstractComposeAction (
locationService,
copyService,
context,
"Duplicate",
"to a location"
);
}
return CopyAction;
*/
/** /**
* The CopyAction is available from context menus and allows a user to * The CopyAction is available from context menus and allows a user to
* deep copy an object to another location of their choosing. * deep copy an object to another location of their choosing.
@ -34,15 +48,21 @@ define(
* @constructor * @constructor
* @memberof platform/entanglement * @memberof platform/entanglement
*/ */
function CopyAction($log, locationService, copyService, dialogService, notificationService, context) { function CopyAction($log, locationService, copyService, dialogService,
notificationService, context) {
this.dialogService = dialogService; this.dialogService = dialogService;
this.notificationService = notificationService; this.notificationService = notificationService;
this.$log = $log; this.$log = $log;
AbstractComposeAction.call(this, locationService, copyService, context, "Duplicate", "to a location"); //Extend the behaviour of the Abstract Compose Action
AbstractComposeAction.call(this, locationService, copyService,
context, "Duplicate", "to a location");
} }
CopyAction.prototype = Object.create(AbstractComposeAction.prototype); /**
* Executes the CopyAction. The CopyAction uses the default behaviour of
* the AbstractComposeAction, but extends it to support notification
* updates of progress on copy.
*/
CopyAction.prototype.perform = function() { CopyAction.prototype.perform = function() {
var self = this, var self = this,
notification, notification,
@ -52,7 +72,18 @@ define(
severity: "info", severity: "info",
}; };
/*
Show banner notification of copy progress.
*/
function progress(phase, totalObjects, processed){ function progress(phase, totalObjects, processed){
/*
Copy has two distinct phases. In the first phase a copy plan is
made in memory. During this phase of execution, the user is
shown a blocking 'modal' dialog.
In the second phase, the copying is taking place, and the user
is shown non-invasive banner notifications at the bottom of the screen.
*/
if (phase.toLowerCase() === 'preparing'){ if (phase.toLowerCase() === 'preparing'){
self.dialogService.showBlockingMessage({ self.dialogService.showBlockingMessage({
title: "Preparing to copy objects", title: "Preparing to copy objects",
@ -62,19 +93,22 @@ define(
} else if (phase.toLowerCase() === "copying") { } else if (phase.toLowerCase() === "copying") {
self.dialogService.dismiss(); self.dialogService.dismiss();
if (!notification) { if (!notification) {
notification = self.notificationService.notify(notificationModel); notification = self.notificationService
.notify(notificationModel);
} }
notificationModel.progress = (processed / totalObjects) * 100; notificationModel.progress = (processed / totalObjects) * 100;
notificationModel.title = ["Copied ", processed, "of ", totalObjects, "objects"].join(" "); notificationModel.title = ["Copied ", processed, "of ",
totalObjects, "objects"].join(" ");
} }
} }
AbstractComposeAction.prototype.perform.call(this, progress) AbstractComposeAction.prototype.perform.call(this)
.then(function(){ .then(
notification.dismiss(); function(){
self.notificationService.info("Copying complete."); notification.dismiss();
}) self.notificationService.info("Copying complete.");
.catch(function (error){ },
function(error){
self.$log.error("Error copying objects. ", error); self.$log.error("Error copying objects. ", error);
//Show more general error message //Show more general error message
self.notificationService.notify({ self.notificationService.notify({
@ -82,7 +116,11 @@ define(
severity: "error", severity: "error",
hint: error.message hint: error.message
}); });
});
},
function(notification){
progress(notification.phase, notification.totalObjects, notification.processed);
})
}; };
return CopyAction; return CopyAction;
} }

View File

@ -68,7 +68,7 @@ define(
* object being copied. The clones are all full composed with * object being copied. The clones are all full composed with
* references to their own children. * references to their own children.
*/ */
CopyService.prototype.buildCopyPlan = function(domainObject, parent) { CopyService.prototype.buildCopyPlan = function(domainObject, parent, progress) {
var clones = [], var clones = [],
$q = this.$q, $q = this.$q,
self = this; self = this;
@ -99,6 +99,8 @@ define(
delete modelClone.model.persisted; delete modelClone.model.persisted;
delete modelClone.model.modified; delete modelClone.model.modified;
return $q.when(originalObject.useCapability('composition')).then(function(composees){ return $q.when(originalObject.useCapability('composition')).then(function(composees){
progress({phase: "preparing"});
return (composees || []).reduce(function(promise, composee){ return (composees || []).reduce(function(promise, composee){
//If the object is composed of other //If the object is composed of other
// objects, chain a promise.. // objects, chain a promise..
@ -120,6 +122,7 @@ define(
}); });
}); });
}; };
return copy(domainObject, parent).then(function(){ return copy(domainObject, parent).then(function(){
return clones; return clones;
}); });
@ -142,7 +145,7 @@ define(
clone.model.persisted = self.now(); clone.model.persisted = self.now();
return self.persistenceService.createObject(clone.persistenceSpace, clone.id, clone.model) return self.persistenceService.createObject(clone.persistenceSpace, clone.id, clone.model)
.then(function(){ .then(function(){
progress && progress("copying", objectClones.length, ++persisted); progress && progress({phase: "copying", totalObjects: objectClones.length, processed: ++persisted});
}); });
})).then(function(){ })).then(function(){
return objectClones return objectClones
@ -184,13 +187,15 @@ define(
* @returns a promise that will be completed with the clone of * @returns a promise that will be completed with the clone of
* domainObject when the duplication is successful. * domainObject when the duplication is successful.
*/ */
CopyService.prototype.perform = function (domainObject, parent, progress) { CopyService.prototype.perform = function (domainObject, parent) {
var $q = this.$q; var $q = this.$q,
deferred = $q.defer();
if (this.validate(domainObject, parent)) { if (this.validate(domainObject, parent)) {
progress && progress("preparing"); this.buildCopyPlan(domainObject, parent, deferred.notify)
return this.buildCopyPlan(domainObject, parent) .then(this.persistObjects(deferred.notify))
.then(this.persistObjects(progress)) .then(this.addClonesToParent(parent, deferred.notify))
.then(this.addClonesToParent(parent, progress)); .then(deferred.resolve);
return deferred.promise;
} else { } else {
throw new Error( throw new Error(
"Tried to copy objects without validating first." "Tried to copy objects without validating first."