mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	WIP: Upload volume UI
Adds new action, upload volume, to the storage->volumes list view header. This will present a dialog to specify URL & name of volume, and select a VM to attach the volume to. Server API calls are still incomplete and rely on hardcoded values.
This commit is contained in:
		
							parent
							
								
									310453f993
								
							
						
					
					
						commit
						57cc1ea378
					
				| @ -1,4 +1,8 @@ | ||||
| #new labels (begin) ********************************************************************************************** | ||||
| message.specify.url=Please specify URL | ||||
| label.select.instance.to.attach.volume.to=Select instance to attach volume to | ||||
| label.upload=Upload | ||||
| label.upload.volume=Upload volume | ||||
| label.virtual.routers=Virtual Routers | ||||
| label.primary.storage.count=Primary Storage Pools | ||||
| label.secondary.storage.count=Secondary Storage Pools | ||||
|  | ||||
| @ -7079,6 +7079,90 @@ div.panel.ui-dialog div.list-view div.fixed-header { | ||||
|   display: none; | ||||
| } | ||||
| 
 | ||||
| /*Upload volume*/ | ||||
| .upload-volume { | ||||
| } | ||||
| 
 | ||||
| .upload-volume .list-view { | ||||
|   margin-top: 5px !important; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .listView-container { | ||||
|   background: #FFFFFF; | ||||
|   width: 823px; | ||||
|   margin: 71px 0px 20px 28px; | ||||
|   border: 1px solid #DADADA; | ||||
|   /*+border-radius:4px;*/ | ||||
|   -moz-border-radius: 4px; | ||||
|   -webkit-border-radius: 4px; | ||||
|   -khtml-border-radius: 4px; | ||||
|   border-radius: 4px 4px 4px 4px; | ||||
| } | ||||
| 
 | ||||
| .upload-volume div.list-view .data-table div.fixed-header { | ||||
|   top: 115px !important; | ||||
|   left: 56px !important; | ||||
|   background: #FFFFFF !important; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .data-table table.body { | ||||
|   margin-top: 66px !important; | ||||
|   margin-left: 19px; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .list-view .toolbar { | ||||
|   top: 118px; | ||||
|   width: 801px; | ||||
|   left: 43px; | ||||
|   background: transparent; | ||||
|   border: none; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .top-fields { | ||||
|   float: left; | ||||
|   clear: none; | ||||
|   margin-left: 24px; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .top-fields .field { | ||||
|   float: left; | ||||
|   margin-right: 50px; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .top-fields input { | ||||
|   float: right; | ||||
|   /*+border-radius:3px;*/ | ||||
|   -moz-border-radius: 3px; | ||||
|   -webkit-border-radius: 3px; | ||||
|   -khtml-border-radius: 3px; | ||||
|   border-radius: 3px 3px 3px 3px; | ||||
|   padding: 2px; | ||||
|   width: 186px; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .top-fields label, | ||||
| .upload-volume .desc { | ||||
|   display: block; | ||||
|   float: left; | ||||
|   padding: 6px; | ||||
|   font-size: 12px; | ||||
|   color: #4C5D6C; | ||||
|   /*+text-shadow:0px 0px #FFFFFF;*/ | ||||
|   -moz-text-shadow: 0px 0px #FFFFFF; | ||||
|   -webkit-text-shadow: 0px 0px #FFFFFF; | ||||
|   -o-text-shadow: 0px 0px #FFFFFF; | ||||
|   text-shadow: 0px 0px #FFFFFF; | ||||
| } | ||||
| 
 | ||||
| .upload-volume .desc { | ||||
|   position: absolute; | ||||
|   width: 825px; | ||||
|   text-align: left; | ||||
|   top: 79px; | ||||
|   left: 32px; | ||||
|   border-top: 1px solid #CFCFCF; | ||||
| } | ||||
| 
 | ||||
| /*Network detail chat*/ | ||||
| .network-chart { | ||||
|   width: 100%; | ||||
| @ -8886,3 +8970,11 @@ div.panel.ui-dialog div.list-view div.fixed-header { | ||||
|   cursor: move !important; | ||||
| } | ||||
| 
 | ||||
| .uploadVolume .icon { | ||||
|   background-position: -232px -34px; | ||||
| } | ||||
| 
 | ||||
| .uploadVolume:hover .icon { | ||||
|   background-position: -230px -615px; | ||||
| } | ||||
| 
 | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 175 KiB After Width: | Height: | Size: 177 KiB | 
| @ -1639,6 +1639,7 @@ | ||||
|     <script src="scripts/ui-custom/securityRules.js" type="text/javascript"></script> | ||||
|     <script src="scripts/network.js" type="text/javascript"></script> | ||||
|     <script src="scripts/ui-custom/recurringSnapshots.js" type="text/javascript"></script> | ||||
|     <script src="scripts/ui-custom/uploadVolume.js" type="text/javascript"></script> | ||||
|     <script src="scripts/storage.js" type="text/javascript"></script> | ||||
|     <script src="scripts/templates.js" type="text/javascript"></script> | ||||
|     <script src="scripts/accounts.js" type="text/javascript"></script> | ||||
| @ -1668,6 +1669,10 @@ | ||||
| 
 | ||||
| <script language="javascript"> | ||||
| dictionary = { | ||||
| 'message.specify.url': '<fmt:message key="message.specify.url"/>', | ||||
| 'label.select.instance.to.attach.volume.to': '<fmt:message key="label.select.instance.to.attach.volume.to"/>', | ||||
| 'label.upload': '<fmt:message key="label.upload"/>', | ||||
| 'label.upload.volume': '<fmt:message key="label.upload.volume"/>', | ||||
| 'label.virtual.routers': '<fmt:message key="label.virtual.routers"/>', | ||||
| 'label.primary.storage.count': '<fmt:message key="label.primary.storage.count"/>', | ||||
| 'label.secondary.storage.count': '<fmt:message key="label.secondary.storage.count"/>', | ||||
|  | ||||
| @ -171,8 +171,74 @@ | ||||
|               notification: { | ||||
|                 poll: pollAsyncJobResult | ||||
|               } | ||||
|             } | ||||
|             }, | ||||
|             uploadVolume: { | ||||
|               isHeader: true, | ||||
|               label: 'label.upload.volume', | ||||
|               messages: { | ||||
|                 notification: function() { return 'label.upload.volume'; } | ||||
|               }, | ||||
|               notification: { poll: function(args) { args.complete(); } }, | ||||
|               action: { | ||||
|                 custom: cloudStack.uiCustom.uploadVolume({ | ||||
|                   listView: $.extend(true, {}, cloudStack.sections.instances, { | ||||
|                     listView: { | ||||
|                       filters: false, | ||||
|                       dataProvider: function(args) { | ||||
|                         var searchByArgs = args.filterBy.search.value && | ||||
|                               args.filterBy.search.value.length ? | ||||
|                               '&name=' + args.filterBy.search.value : ''; | ||||
| 
 | ||||
|                         $.ajax({ | ||||
|                           url: createURL('listVirtualMachines' + searchByArgs), | ||||
|                           data: { | ||||
|                             page: args.page, | ||||
|                             pageSize: pageSize, | ||||
|                             listAll: true | ||||
|                           }, | ||||
|                           dataType: 'json', | ||||
|                           async: true, | ||||
|                           success: function(data) { | ||||
|                             args.response.success({ | ||||
|                               data: $.grep( | ||||
|                                 data.listvirtualmachinesresponse.virtualmachine ? | ||||
|                                   data.listvirtualmachinesresponse.virtualmachine : [], | ||||
|                                 function(instance) { | ||||
|                                   return $.inArray(instance.state, [ | ||||
|                                     'Destroyed', 'Error', 'Stopping', 'Starting' | ||||
|                                   ]) == -1; | ||||
|                                 } | ||||
|                               ) | ||||
|                             }); | ||||
|                           }, | ||||
|                           error: function(data) { | ||||
|                             args.response.error(parseXMLHttpResponse(data)); | ||||
|                           } | ||||
|                         }); | ||||
|                       } | ||||
|                     } | ||||
|                   }), | ||||
|                   action: function(args) { | ||||
|                     $.ajax({ | ||||
|                       url: createURL('uploadVolume'), | ||||
|                       data: { | ||||
|                         hypervisor: 'XenServer', // Replace with instances' hypervisor
 | ||||
|                         format: 'VHD', // Replace with format of uploaded volume
 | ||||
|                         name: args.data.name, | ||||
|                         url: args.data.url, | ||||
|                         zoneid: 1 // Replace with instances' zone ID
 | ||||
|                       }, | ||||
|                       success: function(json) { | ||||
|                         args.response.success(); | ||||
|                       }, | ||||
|                       error: function(json) { | ||||
|                         args.response.error(parseXMLHttpResponse(json)); | ||||
|                       } | ||||
|                     }); | ||||
|                   } | ||||
|                 }) | ||||
|               } | ||||
|             } | ||||
|           }, | ||||
| 
 | ||||
|           dataProvider: function(args) { | ||||
|  | ||||
							
								
								
									
										155
									
								
								ui/scripts/ui-custom/uploadVolume.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								ui/scripts/ui-custom/uploadVolume.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,155 @@ | ||||
| (function(cloudStack, $) { | ||||
|   cloudStack.uiCustom.uploadVolume = function(args) { | ||||
|     var listView = args.listView; | ||||
|     var action = args.action; | ||||
| 
 | ||||
|     var validate = function($uploadVolume) { | ||||
|       if (!$uploadVolume.find('input[type=text]').val()) { | ||||
|         cloudStack.dialog.notice({ message: _l('message.specify.url')}); | ||||
| 
 | ||||
|         return false; | ||||
|       } | ||||
|        | ||||
|       if (!$uploadVolume.find( | ||||
|         'input[type=radio]:checked, input[type=checkbox]:checked' | ||||
|       ).size()) { | ||||
|         cloudStack.dialog.notice({ message: _l('message.select.instance')}); | ||||
| 
 | ||||
|         return false; | ||||
|       } | ||||
| 
 | ||||
|       return true; | ||||
|     }; | ||||
| 
 | ||||
|     return function(args) { | ||||
|       var $uploadVolume = $('<div>').addClass('upload-volume'); | ||||
|       var context = args.context; | ||||
|       var topFields = function() { | ||||
|         var $form = $('<form>').addClass('top-fields'); | ||||
|         var $urlLabel = $('<label>').html(_l('label.url') + ':'); | ||||
|         var $urlField = $('<div>').addClass('field url'); | ||||
|         var $nameLabel = $('<label>').html(_l('label.name') + ':'); | ||||
|         var $nameField = $('<div>').addClass('field name'); | ||||
|         var $urlInput = $('<input>').attr({ | ||||
|           type: 'text', | ||||
|           name: 'url' | ||||
|         }).addClass('required'); | ||||
|         var $nameInput = $('<input>').attr({ | ||||
|           type: 'text', | ||||
|           name: 'name' | ||||
|         }).addClass('required'); | ||||
| 
 | ||||
|         $urlField.append($urlLabel, $urlInput); | ||||
|         $nameField.append($nameLabel, $nameInput); | ||||
|         $form.append($nameField, $urlField); | ||||
| 
 | ||||
|         return $form; | ||||
|       }; | ||||
|       var vmList = function(args) { | ||||
|         // Create a listing of instances, based on limited information
 | ||||
|         // from main instances list view
 | ||||
|         var $listView; | ||||
|         var instances = $.extend(true, {}, args.listView, { | ||||
|           context: context, | ||||
|           uiCustom: true | ||||
|         }); | ||||
| 
 | ||||
|         instances.listView.actions = { | ||||
|           select: { | ||||
|             label: _l('label.select.instance'), | ||||
|             type: 'radio', | ||||
|             action: { | ||||
|               uiCustom: function(args) { | ||||
|                 var $item = args.$item; | ||||
|                 var $input = $item.find('td.actions input:visible'); | ||||
| 
 | ||||
|                 if ($input.attr('type') == 'checkbox') { | ||||
|                   if ($input.is(':checked')) | ||||
|                     $item.addClass('multi-edit-selected'); | ||||
|                   else | ||||
|                     $item.removeClass('multi-edit-selected'); | ||||
|                 } else { | ||||
|                   $item.siblings().removeClass('multi-edit-selected'); | ||||
|                   $item.addClass('multi-edit-selected'); | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }; | ||||
| 
 | ||||
|         $listView = $('<div>').listView(instances); | ||||
| 
 | ||||
|         // Change action label
 | ||||
|         $listView.find('th.actions').html(_l('label.select')); | ||||
| 
 | ||||
|         return $listView; | ||||
|       }; | ||||
| 
 | ||||
|       $uploadVolume.append( | ||||
|         topFields, | ||||
|         $('<div>').addClass('desc').html(_l('label.select.instance.to.attach.volume.to') + ':'), | ||||
|         $('<div>').addClass('listView-container').append( | ||||
|           vmList({ listView: listView })  | ||||
|         ) | ||||
|       ); | ||||
|       $uploadVolume.dialog({ | ||||
|         dialogClass: 'multi-edit-add-list panel', | ||||
|         width: 900, | ||||
|         title: _l('label.upload.volume'), | ||||
|         buttons: [ | ||||
|           { | ||||
|             text: _l('label.upload'), | ||||
|             'class': 'ok', | ||||
|             click: function() { | ||||
|               if (!validate($uploadVolume)) return false; | ||||
| 
 | ||||
|               var complete = args.complete; | ||||
|               var $loading = $('<div>').addClass('loading-overlay'); | ||||
| 
 | ||||
|               $loading.appendTo($uploadVolume); | ||||
|               action({ | ||||
|                 data: cloudStack.serializeForm($uploadVolume.find('form')), | ||||
|                 context: $.extend(true, {}, context, { | ||||
|                   instances: [ | ||||
|                     $uploadVolume.find('tr.multi-edit-selected').data('json-obj') | ||||
|                   ] | ||||
|                 }), | ||||
|                 response: { | ||||
|                   success: function(args) { | ||||
|                     $('.ui-dialog').fadeOut(function() { | ||||
|                       $('.ui-dialog').remove(); | ||||
|                       $(window).trigger('cloudStack.fullRefresh'); | ||||
|                     }); | ||||
|                     $('div.overlay').fadeOut(function() { | ||||
|                       $('div.overlay').remove(); | ||||
|                     }); | ||||
|                     complete({ | ||||
|                       $item: $('<div>'), | ||||
|                       _custom: args._custom | ||||
|                     }); | ||||
|                   }, | ||||
|                   error: function(args) { | ||||
|                     $loading.remove(); | ||||
|                     cloudStack.dialog.notice({ message: args }); | ||||
|                   } | ||||
|                 } | ||||
|               }); | ||||
|             } | ||||
|           }, | ||||
|           { | ||||
|             text: _l('label.cancel'), | ||||
|             'class': 'cancel', | ||||
|             click: function() { | ||||
|               $('.ui-dialog').fadeOut(function() { | ||||
|                 $('.ui-dialog').remove(); | ||||
|               }); | ||||
|               $('div.overlay').fadeOut(function() { | ||||
|                 $('div.overlay').remove(); | ||||
|               }); | ||||
|             } | ||||
|           } | ||||
|         ] | ||||
|       }).closest('.ui-dialog').overlay(); | ||||
|     }; | ||||
|   }; | ||||
| }(cloudStack, jQuery)); | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user