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) **********************************************************************************************
|
#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.virtual.routers=Virtual Routers
|
||||||
label.primary.storage.count=Primary Storage Pools
|
label.primary.storage.count=Primary Storage Pools
|
||||||
label.secondary.storage.count=Secondary 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;
|
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 detail chat*/
|
||||||
.network-chart {
|
.network-chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -8886,3 +8970,11 @@ div.panel.ui-dialog div.list-view div.fixed-header {
|
|||||||
cursor: move !important;
|
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/ui-custom/securityRules.js" type="text/javascript"></script>
|
||||||
<script src="scripts/network.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/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/storage.js" type="text/javascript"></script>
|
||||||
<script src="scripts/templates.js" type="text/javascript"></script>
|
<script src="scripts/templates.js" type="text/javascript"></script>
|
||||||
<script src="scripts/accounts.js" type="text/javascript"></script>
|
<script src="scripts/accounts.js" type="text/javascript"></script>
|
||||||
@ -1668,6 +1669,10 @@
|
|||||||
|
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
dictionary = {
|
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.virtual.routers': '<fmt:message key="label.virtual.routers"/>',
|
||||||
'label.primary.storage.count': '<fmt:message key="label.primary.storage.count"/>',
|
'label.primary.storage.count': '<fmt:message key="label.primary.storage.count"/>',
|
||||||
'label.secondary.storage.count': '<fmt:message key="label.secondary.storage.count"/>',
|
'label.secondary.storage.count': '<fmt:message key="label.secondary.storage.count"/>',
|
||||||
|
|||||||
@ -171,8 +171,74 @@
|
|||||||
notification: {
|
notification: {
|
||||||
poll: pollAsyncJobResult
|
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) {
|
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