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