Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

EUCA-3905: New notification implementation for multi-ops

  • Loading branch information...
commit c6f61c6e552f0f5b4859caa406cdfa7dfbd6ce75 1 parent c1158e3
Sang-Min Park sangmin authored
20 console/static/css/eucalyptus.css
View
@@ -118,7 +118,7 @@ ol li {
.euca-notification-container {
position: relative; /* Needed so z-index will be respected */
- z-index: 10;
+ z-index: 11;
}
.euca-main-outercontainer {
@@ -466,8 +466,24 @@ ol li {
font-size: 1.2em;
}
-#euca-notification-desc {
+#euca-notification-progress {
+ display: none;
+ position: relative;
+ width: 700px;
+ left: 130px;
+}
+#euca-notification-desc .multiop-summary-success {
+ margin-top: 10px;
+}
+
+#euca-notification-desc .multiop-summary-failure {
+}
+
+#euca-notification-desc textarea {
+ width: 600px;
+ height: 200px;
+ margin: 10px;
}
#euca-notification-close a {
24 console/static/custom/Messages.properties
View
@@ -66,6 +66,9 @@ keypair_create_error = Failed to create key pair {0}. Please try again.
keypair_delete_success = Deleted keypair {0}. It may take a few minutes for the state to be updated in your table view.
keypair_delete_error = Failed to delete key pair {0}. Please try again.
+keypair_delete_progress = Deleting {0} key pair(s).
+keypair_delete_done = Started deleting {0} of {1} key pair(s).
+keypair_delete_fail = Failed to delete {0} key pair(s). <a href="#">Click here for details. </a>
keypair_import_success = Imported key pair {0}. It may take a few minutes for the state to be updated in your table view.
keypair_import_error = Failed to import key pair {0}. Please try again.
@@ -124,6 +127,9 @@ sgroup_create_error = Failed to create security group {0}. Please try again.
sgroup_delete_success = Deleted security group {0}. It may take a few minutes for the state to be updated in your table view.
sgroup_delete_error = Failed to delete security group {0}. Please try again.
+sgroup_delete_progress = Deleting {0} security group(s).
+sgroup_delete_done = Started deleting {0} of {1} security group(s).
+sgroup_delete_fail = Failed to delete {0} security group(s). <a href="#">Click here for details. </a>
sgroup_dialog_add_title = Create new security group
sgroup_dialog_del_title = Delete security group
@@ -200,6 +206,9 @@ volume_dialog_del_text = <p>All data on the volumes will be destroyed.</p> <p>A
volume_dialog_del_btn = Yes, delete
volume_delete_success = Started delete volume operation for volume {0}. It may take a few minutes for the state to be updated in your table view.
volume_delete_error = Failed to start delete operation for volume {0}. Please try again.
+volume_delete_progress = Deleting {0} volume(s).
+volume_delete_done = Started deleting {0} of {1} volume(s).
+volume_delete_fail = Failed to delete {0} volume(s). <a href="#">Click here for details. </a>
#[volume detach and force detach dialogs]
volume_dialog_detach_title = Detach volumes
@@ -207,6 +216,9 @@ volume_dialog_detach_text = <p>If you detach a volume, the instance can no longe
volume_dialog_detach_btn = Yes, detach
volume_detach_success = Started detach volume operation for volume {0}. It may take a few minutes for the state to be updated in your table view.
volume_detach_error = Failed to start volume detach operation for volume {0}. Please try again.
+volume_detach_progress = Detaching {0} volume(s).
+volume_detach_done = Started detaching {0} of {1} volume(s).
+volume_detach_fail = Failed to detach {0} volume(s). <a href="#">Click here for details. </a>
#[volume create dialog]
volume_dialog_create_btn = Create volume
@@ -288,6 +300,9 @@ snapshot_delete_dialog_title = Delete snapshots
snapshot_dialog_del_btn = Yes, delete
snapshot_delete_success = Started delete operation for snapshot {0}. It may take a few minutes for the state to be updated in your table view.
snapshot_delete_error = Failed to start delete operation for snapshot {0}. Please try again.
+snapshot_delete_progress = Deleting {0} snapshot(s).
+snapshot_delete_done = Started deleting {0} of {1} snapshot(s).
+snapshot_delete_fail = Failed to delete {0} snapshot(s). <a href="#">Click here for details. </a>
#[snapshot register dialog]
snapshot_register_dialog_text = You can register a snapshot as an image if it was created from a volume containing a root file system. The image can then be used to launch EBS-backed instances.
@@ -327,6 +342,9 @@ eip_allocate_dialog_count_label = How many IP addresses would you like to alloca
eip_allocate_dialog_count_tip = Enter the number of IP addresses to allocate.
eip_allocate_success = Allocated new IP addresses. It may take a few minutes for the state to be updated in your table view.
eip_allocate_error = Unable to allocate all the requested IP addresses. Please verify you are allowed to manage more IP addresses than you currently have and then try again.
+eip_allocate_progress = Allocating {0} IP address(es).
+eip_allocate_done = Started allocating {0} of {1} IP address(es).
+eip_allocate_fail = Failed to allocate {0} IP address(es). <a href="#">Click here for details. </a>
eip_allocate_count_error_msg = Please specify a whole number
#[IP associate dialog]
@@ -345,6 +363,9 @@ eip_release_dialog_title = Release IP address to cloud
eip_release_dialog_release_btn = Yes, release
eip_release_success = IP addresses released back to the cloud. It may take a few minutes for the state to be updated in your table view.
eip_release_error = Unable to release the specified IP addresses back to the cloud. Please try again.
+eip_release_progress = Releasing {0} IP address(es).
+eip_release_done = Started releasing {0} of {1} IP address(es).
+eip_release_fail = Failed to release {0} IP address(es). <a href="#">Click here for details. </a>
#[IP disassociate dialog]
eip_disassociate_dialog_text = <p>If you disassociate an IP address from an instance, you will no longer be able to connect to that instance using that IP address.</p> <p>Are you sure you want to disassociate the following IP addresses from their instances?</p>
@@ -352,6 +373,9 @@ eip_disassociate_dialog_title = Disassociate IP address from instance
eip_disassociate_dialog_disassociate_btn = Yes, disassociate
eip_disassociate_success = {0} disassociated from instance. It may take a few minutes for the state to be updated in your table view.
eip_disassociate_error = Could not disassociate IP {0} from instance. Please try again.
+eip_disassociate_progress = Disassociating {0} IP address(es).
+eip_disassociate_done = Started disassociating {0} of {1} IP address(es).
+eip_disassociate_fail = Failed to disassociate {0} IP address(es). <a href="#">Click here for details. </a>
#[instance]
instance_h_title = Manage instances
5 console/static/index.html
View
@@ -107,7 +107,10 @@
<div id="euca-notification" class="notification-box clearfix">
<div id="euca-notification-close"> </div>
<div id="euca-notification-title"> </div>
- <div id="euca-notification-desc"> </div>
+ <div id="euca-notification-desc-wrapper">
+ <div id="euca-notification-progress"> </div>
+ <div id="euca-notification-desc"> </div>
+ </div>
</div>
</div>
</div>
97 console/static/js/eip.js
View
@@ -240,6 +240,10 @@
_releaseListedIps : function (rowsToDelete) {
var thisObj = this;
+ var done = 0;
+ var all = rowsToDelete.length;
+ var error = [];
+
doMultiAjax(rowsToDelete, function(item, dfd){
var eipId = item;
$.ajax({
@@ -254,28 +258,43 @@
(function(eipId) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == true ) {
- notifySuccess(null, $.i18n.prop('eip_release_success', eipId));
- dfd.resolve();
+ ;
} else {
- notifyError($.i18n.prop('eip_release_error', eipId), undefined_error);
- dfd.reject();
+ error.push({id:eipId, reason: undefined_reason});
}
}
})(eipId),
error:
(function(eipId) {
return function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('eip_release_error', eipId), getErrorMessage(jqXHR));
- dfd.reject();
+ error.push({id:eipId, reason: getErrorMessage(jqXHR)});
}
- })(eipId)
+ })(eipId),
+ complete: (function(eipId) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('eip_release_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('eip_release_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('eip_release_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
+ }
+ })(eipId),
});
- });
+ }, 100);
thisObj.tableWrapper.eucatable('refreshTable');
},
_disassociateListedIps : function (ipsToDisassociate) {
var thisObj = this;
+ var done = 0;
+ var all = ipsToDisassociate.length;
+ var error = [];
doMultiAjax(ipsToDisassociate, function(item, dfd){
var eipId = item;
$.ajax({
@@ -290,23 +309,35 @@
(function(eipId) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == true ) {
- notifySuccess(null, $.i18n.prop('eip_disassociate_success', eipId));
- dfd.resolve();
+ ;
} else {
- notifyError($.i18n.prop('eip_disassociate_error', eipId), undefined_error);
- dfd.reject();
+ error.push({id:eipId, reason: undefined_reason});
}
}
})(eipId),
error:
(function(eipId) {
return function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('eip_disassociate_error', eipId), getErrorMessage(jqXHR));
- dfd.reject();
+ error.push({id:eipId, reason: getErrorMessage(jqXHR)});
+ }
+ })(eipId),
+ complete: (function(eipId) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('eip_disassociate_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('eip_disassociate_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('eip_disassociate_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
}
- })(eipId)
+ })(eipId),
});
- });
+ }, 100);
thisObj.tableWrapper.eucatable('refreshTable');
},
@@ -316,6 +347,9 @@
for ( i=0; i<numberIpsToAllocate; i++)
arrayIps.push(0);
+ var done = 0;
+ var all = arrayIps.length;
+ var error = [];
var allocatedIps = [];
doMultiAjax(arrayIps, function(item, dfd){
$.ajax({
@@ -326,25 +360,32 @@
cache:false,
timeout:PROXY_TIMEOUT,
async:false,
- success:
- function(data, textStatus, jqXHR){
+ success: function(data, textStatus, jqXHR){
if ( data.results ) {
ip = data.results.public_ip;
allocatedIps.push(ip);
- notifySuccess(null, $.i18n.prop('eip_allocate_success', ip));
- dfd.resolve();
} else {
- notifyError($.i18n.prop('eip_allocate_error'), undefined_error);
- dfd.reject();
+ error.push({id:'unknown', reason: undefined_reason});
}
- },
- error:
- function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('eip_allocate_error'), getErrorMessage(jqXHR));
- dfd.reject();
+ },
+ error: function(jqXHR, textStatus, errorThrown){
+ error.push({id:'unknown', reason: getErrorMessage(jqXHR)});
+ },
+ complete: function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('eip_allocate_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('eip_allocate_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('eip_allocate_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
}
+ dfd.resolve();
+ }
});
- });
+ }, 100);
thisObj.tableWrapper.eucatable('refreshTable');
$.each(allocatedIps, function(idx, ip){
thisObj.tableWrapper.eucatable('glowRow', ip);
45 console/static/js/instance.js
View
@@ -498,7 +498,6 @@
success: function(data, textStatus, jqXHR){
if ( data.results && data.results == true ) {
notifySuccess(null, $.i18n.prop('instance_reboot_success', instances));
- thisObj.tableWrapper.eucatable('refreshTable');
} else {
notifyError($.i18n.prop('instance_reboot_error', instances), undefined_error);
}
@@ -747,10 +746,16 @@
_detachVolume : function (force) {
var thisObj = this;
-
- var selectedVolumes = thisObj.detachDialog.find("input:checked");
+ var checkedVolumes = thisObj.detachDialog.find("input:checked");
+ var selectedVolumes = [];
+ $.each(checkedVolumes, function(idx, vol){
+ selectedVolumes.push($(vol).val());
+ });
+ var done = 0;
+ var all = selectedVolumes.length;
+ var error = [];
doMultiAjax(selectedVolumes, function(item, dfd){
- var volumeId = $(item).val();
+ var volumeId = item;
$.ajax({
type:"POST",
url:"/ec2?Action=DetachVolume",
@@ -760,20 +765,32 @@
success: (function(volumeId) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == 'detaching' ) {
- notifySuccess(null, volume_detach_success(volumeId));
- dfd.resolve();
- } else {
- notifyError($.i18n.prop('volume_detach_error', volumeId), undefined_error);
- dfd.reject();
- }
- }
+ ;
+ }else{
+ error.push({id:volumeId, reason: undefined_reason});
+ }
+ }
})(volumeId),
error: (function(volumeId) {
return function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('volume_detach_error', volumeId), getErrorMessage(jqXHR));
- dfd.reject();
+ error.push({id:volumeId, reason: getErrorMessage(jqXHR)});
}
- })(volumeId)
+ })(volumeId),
+ complete: (function(volumeId) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('volume_detach_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('volume_detach_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('volume_detach_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
+ }
+ })(volumeId),
});
});
thisObj.tableWrapper.eucatable('refreshTable');
36 console/static/js/keypair.js
View
@@ -239,6 +239,10 @@
_deleteSelectedKeyPairs : function (keysToDelete) {
var thisObj = this;
+ var done = 0;
+ var all = keysToDelete.length;
+ var error = [];
+
doMultiAjax(keysToDelete, function(item, dfd){
var keyName = item;
$.ajax({
@@ -248,25 +252,35 @@
dataType:"json",
timeout:PROXY_TIMEOUT,
async:true,
- success:
- (function(keyName) {
+ success: (function(keyName) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == true ) {
- notifySuccess(null, $.i18n.prop('keypair_delete_success', keyName));
- dfd.resolve();
+ ;
} else {
- notifyError($.i18n.prop('keypair_delete_error', keyName), undefined_error);
- dfd.reject();
+ error.push({id:keyName, reason: undefined_reason});
}
}
})(keyName),
- error:
- (function(keyName) {
+ error: (function(keyName) {
return function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('keypair_delete_error', keyName), getErrorMessage(jqXHR));
- dfd.reject();
+ error.push({id:keyName, reason: getErrorMessage(jqXHR)});
}
- })(keyName)
+ })(keyName),
+ complete: (function(keyName) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('keypair_delete_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('keypair_delete_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('keypair_delete_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
+ }
+ })(keyName),
});
});
thisObj.tableWrapper.eucatable('refreshTable');
74 console/static/js/notification.js
View
@@ -49,6 +49,76 @@
},
/*
+ args.percent : percentage of the progress
+ args.desc : message after progress (e.g., 95/100 volumes deleted. Failed to delete 5 vollumes)
+ args.error: : [ {id:.., reason:.., code: }, {id:.., reason: .., code: } ]
+ */
+ multi : function(args) {
+ var thisObj = this;
+ var percent = args.percent;
+ var desc = args.desc;
+ var error = args.error;
+
+ // if (id !== thisObj.element.attr('progress-id'))
+ // return;
+
+ percent = Math.min(100, percent);
+ percent = Math.max(0, percent);
+ thisObj.element.find('#euca-notification-progress').progressbar({value: percent});
+ thisObj.element.find('#euca-notification-progress').show();
+ if(desc)
+ thisObj.element.find('#euca-notification-desc').html(desc);
+
+ // check if the notification is in progress-mode and the id is for this progress report
+ // toggle and show the progress
+ if( !this.element.hasClass('toggle-on') && !thisObj.element.attr('in-progress') ){
+ this.element.slideToggle('fast');
+ this.element.toggleClass('toggle-on');
+ }
+
+ // set the percentage
+ if( percent === 100){
+ // now set the description and error
+ thisObj.element.find('#euca-notification-desc a').click(function(e) {
+ if(thisObj.element.find('#euca-notification-desc .euca-notification-error').length <=0){
+ var errorMsg = '';
+ $.each(error, function(idx, err){
+ if(!err.code)
+ errorMsg += err.id+': '+err.reason+'\n';
+ else
+ errorMsg += err.id+': '+err.reason+'('+err.code+')\n';
+ });
+ thisObj.element.find('#euca-notification-desc').append(
+ $('<div>').addClass('euca-notification-error').append(
+ $('<textarea>').attr('id','euca-notification-error-list').attr('disabled','true').val(errorMsg)));
+ }else
+ thisObj.element.find('#euca-notification-desc .euca-notification-error').detach();
+ });
+ thisObj.element.removeAttr('in-progress');
+ if(error && error.length > 0)
+ this.element.removeClass('success-msg').addClass('error-msg');
+ else{
+ this.element.removeClass('error-msg').addClass('success-msg');
+ setTimeout(function(){
+ thisObj.element.find('#euca-notification-close a').trigger('click');
+ }, 5000);
+ }
+ // check if the notification is in progress-mode and the id is for this progress report
+ // toggle and show the progress
+ if( !this.element.hasClass('toggle-on') ){
+ this.element.slideToggle('fast');
+ this.element.toggleClass('toggle-on');
+ }
+ }else{
+ if( !this.element.hasClass('toggle-on') && !thisObj.element.attr('in-progress') ){
+ this.element.slideToggle('fast');
+ this.element.toggleClass('toggle-on');
+ }
+ thisObj.element.attr('in-progress','true');
+ }
+ },
+
+ /*
args.success : boolean
args.title : title of the notification
args.desc : textual description of the notification
@@ -56,6 +126,10 @@
*/
notify : function(args) {
var thisObj = this;
+ // override notifyMulti if invoked
+ thisObj.element.removeAttr('in-progress');
+ thisObj.element.find('#euca-notification-progress').hide();
+
if(args.title){
this.element.find('#euca-notification-title').html(args.title);
this.element.find('#euca-notification-title').show();
39 console/static/js/sgroup.js
View
@@ -708,9 +708,16 @@
_deleteSelectedSecurityGroups : function () {
var thisObj = this;
- var rowsToDelete = thisObj._getTableWrapper().eucatable('getSelectedRows', 1);
+ var toDelete = thisObj._getTableWrapper().eucatable('getSelectedRows', 1);
+ var rowsToDelete = [];
+ $.each(toDelete, function(idx, item){
+ rowsToDelete.push($(item).val());
+ });
+ var done = 0;
+ var all = rowsToDelete.length;
+ var error = [];
doMultiAjax(rowsToDelete, function(item, dfd){
- var sgroupName = $(item).html();
+ var sgroupName = item;
$.ajax({
type:"POST",
url:"/ec2?Action=DeleteSecurityGroup",
@@ -721,20 +728,32 @@
success: (function(sgroupName, refresh_table) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == true ) {
- notifySuccess(null, $.i18n.prop('sgroup_delete_success', sgroupName));
- dfd.resolve();
+ ;
} else {
- notifyError($.i18n.prop('sgroup_delete_error', sgroupName), undefined_error);
- dfd.reject();
+ error.push({id:sgroupName, reason: undefined_reason});
}
- }
+ }
})(sgroupName),
error: (function(sgroupName) {
return function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('sgroup_delete_error', sgroupName), errorThrown);
- dfd.reject();
+ error.push({id:sgroupName, reason: getErrorMessage(jqXHR)});
}
- })(sgroupName)
+ })(sgroupName),
+ complete: (function(sgroupName) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('sgroup_delete_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('sgroup_delete_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('sgroup_delete_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
+ }
+ })(sgroupName),
});
});
thisObj._getTableWrapper().eucatable('refreshTable');
36 console/static/js/snapshot.js
View
@@ -284,6 +284,10 @@
_deleteListedSnapshots : function (snapshotsToDelete) {
var thisObj = this;
+ var done = 0;
+ var all = snapshotsToDelete.length;
+ var error = [];
+
doMultiAjax(snapshotsToDelete, function(item, dfd){
var snapshotId = item;
$.ajax({
@@ -293,25 +297,35 @@
dataType:"json",
timeout:PROXY_TIMEOUT,
async:true,
- success:
- (function(snapshotId) {
+ success: (function(snapshotId) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == true ) {
- notifySuccess(null,$.i18n.prop('snapshot_delete_success', snapshotId));
- dfd.resolve();
+ ;
} else {
- notifyError($.i18n.prop('snapshot_delete_error', snapshotId), undefined_error);
- dfd.reject();
+ error.push({id:snapshotId, reason: undefined_reason});
}
}
})(snapshotId),
- error:
- (function(snapshotId) {
+ error: (function(snapshotId) {
return function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('snapshot_delete_error', snapshotId), getErrorMessage(jqXHR));
- dfd.reject();
+ error.push({id:snapshotId, reason: getErrorMessage(jqXHR)});
}
- })(snapshotId)
+ })(snapshotId),
+ complete: (function(snapshotId) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('snapshot_delete_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('snapshot_delete_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('snapshot_delete_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
+ }
+ })(snapshotId),
});
});
thisObj.tableWrapper.eucatable('refreshTable');
31 console/static/js/support.js
View
@@ -126,6 +126,10 @@ function notifyError(title, message, proxyMessage, code) {
$('html body').find(DOM_BINDING['notification']).notification('error', title, desc, code);
}
+function notifyMulti(percent, desc, error){
+ $('html body').find(DOM_BINDING['notification']).notification('multi', {percent:percent,desc:desc,error:error });
+}
+
function allInArray(val_arr, larger_arr){
var ret = true;
for (i in val_arr){
@@ -489,17 +493,26 @@ function setupAjax(){
});
}
-function doMultiAjax(array, callback){
- if (!array || !callback)
+function doMultiAjax(array, callback, delayMs){
+ if (!array || array.length <=0 || !callback)
return;
- for (i = 0; i<array.length; i++){
+ var i =0;
+ var doNext = function(array, i){
$.when(
(function(){
- var dfd = $.Deferred();
- callback(array[i],dfd);
- dfd.promise();
+ var dfd = new $.Deferred();
+ callback(array[i], dfd);
+ return dfd.promise();
})()
- ).done(function() { ; })
- .fail(function() { ; });
- }
+ ).always(function() {
+ if( i+1 < array.length){
+ if(delayMs && delayMs > 0)
+ setTimeout(function(){return doNext(array, i+1)}, delayMs);
+ else
+ doNext(array, i+1);
+ }
+ });
+ };
+
+ doNext(array, 0);
}
74 console/static/js/volume.js
View
@@ -388,6 +388,9 @@
_deleteListedVolumes : function (volumesToDelete) {
var thisObj = this;
+ var done = 0;
+ var all = volumesToDelete.length;
+ var error = [];
doMultiAjax(volumesToDelete, function(item, dfd){
var volumeId = item;
$.ajax({
@@ -401,21 +404,35 @@
(function(volumeId) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == true ) {
- notifySuccess(null, $.i18n.prop('volume_delete_success', volumeId));
- dfd.resolve();
+ ;
} else {
- notifyError($.i18n.prop('volume_delete_error', volumeId), undefined_error);
- dfd.reject();
+ error.push({id:volumeId, reason: undefined_reason});
}
}
})(volumeId),
error:
(function(volumeId) {
return function(jqXHR, textStatus, errorThrown){
- notifyError($.i18n.prop('volume_delete_error', volumeId), getErrorMessage(jqXHR));
- dfd.reject();
+ error.push({id:volumeId, reason: getErrorMessage(jqXHR)});
}
- })(volumeId)
+ })(volumeId),
+ complete:
+ (function(volumeId) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('volume_delete_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('volume_delete_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('volume_delete_fail', error.length)));
+
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
+ }
+ })(volumeId),
});
});
thisObj.tableWrapper.eucatable('refreshTable');
@@ -474,7 +491,9 @@
_detachListedVolumes : function (volumes, force) {
var thisObj = this;
- dialogToUse = this.detachDialog;
+ var done = 0;
+ var all = volumes.length;
+ var error = [];
doMultiAjax( volumes, function(item, dfd){
var volumeId = item;
$.ajax({
@@ -484,32 +503,33 @@
dataType:"json",
timeout:PROXY_TIMEOUT,
async:true,
- success:
- (function(volumeId) {
+ success: (function(volumeId) {
return function(data, textStatus, jqXHR){
if ( data.results && data.results == 'detaching' ) {
- if (force)
- notifySuccess(null, $.i18n.prop('volume_force_detach_success', volumeId));
- else
- notifySuccess(null, $.i18n.prop('volume_detach_success', volumeId));
- dfd.resolve();
+ ;
} else {
- if (force)
- notifyError($.i18n.prop('volume_force_detach_error', volumeId), undefined_error);
- else
- notifyError($.i18n.prop('volume_detach_error', volumeId), undefined_error);
- dfd.reject();
+ error.push({id:volumeId, reason: undefined_reason});
}
}
})(volumeId),
- error:
- (function(volumeId) {
+ error: (function(volumeId) {
return function(jqXHR, textStatus, errorThrown){
- if (force)
- notifyError($.i18n.prop('volume_force_detach_error', volumeId), getErrorMessage(jqXHR));
- else
- notifyError($.i18n.prop('volume_detach_error', volumeId), getErrorMessage(jqXHR));
- dfd.reject();
+ error.push({id:volumeId, reason: getErrorMessage(jqXHR)});
+ }
+ })(volumeId),
+ complete: (function(volumeId) {
+ return function(jqXHR, textStatus){
+ done++;
+ if(done < all)
+ notifyMulti(100*(done/all), $.i18n.prop('volume_detach_progress', all));
+ else {
+ var $msg = $('<div>').addClass('multiop-summary').append(
+ $('<div>').addClass('multiop-summary-success').html($.i18n.prop('volume_detach_done', (all-error.length), all)));
+ if (error.length > 0)
+ $msg.append($('<div>').addClass('multiop-summary-failure').html($.i18n.prop('volume_detach_fail', error.length)));
+ notifyMulti(100, $msg.html(), error);
+ }
+ dfd.resolve();
}
})(volumeId)
});
Please sign in to comment.
Something went wrong with that request. Please try again.