Commit 1a9d84cd by Kálmán Viktor

Merge branch 'master' into issue-364

Conflicts:
	circle/dashboard/static/dashboard/vm-common.js
	circle/dashboard/templates/dashboard/store/index-files.html
parents 29adb58a e70e03b7
...@@ -198,6 +198,7 @@ PIPELINE_JS = { ...@@ -198,6 +198,7 @@ PIPELINE_JS = {
"jquery-knob/dist/jquery.knob.min.js", "jquery-knob/dist/jquery.knob.min.js",
"jquery-simple-slider/js/simple-slider.js", "jquery-simple-slider/js/simple-slider.js",
"dashboard/dashboard.js", "dashboard/dashboard.js",
"dashboard/activity.js",
"dashboard/group-details.js", "dashboard/group-details.js",
"dashboard/group-list.js", "dashboard/group-list.js",
"dashboard/js/stupidtable.min.js", # no bower file "dashboard/js/stupidtable.min.js", # no bower file
......
...@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None): ...@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None):
"in the 'target_cls' parameter to this " "in the 'target_cls' parameter to this "
"call.") "call.")
assert not hasattr(target_cls, op_id), (
"target class already has an attribute with this id")
if not issubclass(target_cls, OperatedMixin): if not issubclass(target_cls, OperatedMixin):
raise TypeError("%r is not a subclass of %r" % raise TypeError("%r is not a subclass of %r" %
(target_cls.__name__, OperatedMixin.__name__)) (target_cls.__name__, OperatedMixin.__name__))
......
...@@ -898,7 +898,7 @@ class VmDownloadDiskForm(OperationForm): ...@@ -898,7 +898,7 @@ class VmDownloadDiskForm(OperationForm):
def clean(self): def clean(self):
cleaned_data = super(VmDownloadDiskForm, self).clean() cleaned_data = super(VmDownloadDiskForm, self).clean()
if not cleaned_data['name']: if not cleaned_data['name']:
if cleaned_data['url']: if cleaned_data.get('url'):
cleaned_data['name'] = urlparse( cleaned_data['name'] = urlparse(
cleaned_data['url']).path.split('/')[-1] cleaned_data['url']).path.split('/')[-1]
if not cleaned_data['name']: if not cleaned_data['name']:
...@@ -908,6 +908,36 @@ class VmDownloadDiskForm(OperationForm): ...@@ -908,6 +908,36 @@ class VmDownloadDiskForm(OperationForm):
return cleaned_data return cleaned_data
class VmRemoveInterfaceForm(OperationForm):
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
self.interface = kwargs.pop('default')
super(VmRemoveInterfaceForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'interface', forms.ModelChoiceField(
queryset=choices, initial=self.interface, required=True,
empty_label=None, label=_('Interface')))
if self.interface:
self.fields['interface'].widget = HiddenInput()
@property
def helper(self):
helper = super(VmRemoveInterfaceForm, self).helper
if self.interface:
helper.layout = Layout(
AnyTag(
"div",
HTML(format_html(
_("<label>Vlan:</label> {0}"),
self.interface.vlan)),
css_class="form-group",
),
Field("interface"),
)
return helper
class VmAddInterfaceForm(OperationForm): class VmAddInterfaceForm(OperationForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices') choices = kwargs.pop('choices')
......
/* for functions in both vm list and vm detail */
$(function() { $(function() {
var in_progress = false;
var activity_hash = 5;
var show_all = false;
var reload_vm_detail = false;
/* do we need to check for new activities */
if(decideActivityRefresh()) {
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
}
/* vm operations */ $('a[href="#activity"]').click(function(){
$('a[href="#activity"] i').addClass('fa-spin');
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
});
$("#activity-refresh").on("click", "#show-all-activities", function() {
$(this).find("i").addClass("fa-spinner fa-spin");
show_all = !show_all;
$('a[href="#activity"]').trigger("click");
return false;
});
/* operations */
$('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) { $('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) {
var icon = $(this).children("i").addClass('fa-spinner fa-spin'); var icon = $(this).children("i").addClass('fa-spinner fa-spin');
...@@ -23,11 +48,9 @@ $(function() { ...@@ -23,11 +48,9 @@ $(function() {
}); });
/* if the operation fails show the modal again */ /* if the operation fails show the modal again */
$("body").on("click", "#op-form-send", function() { $("body").on("click", "#confirmation-modal #op-form-send", function() {
var url = $(this).closest("form").prop("action"); var url = $(this).closest("form").prop("action");
$(this).find("i").prop("class", "fa fa-fw fa-spinner fa-spin");
$.ajax({ $.ajax({
url: url, url: url,
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
...@@ -79,4 +102,91 @@ $(function() { ...@@ -79,4 +102,91 @@ $(function() {
return false; return false;
}); });
function decideActivityRefresh() {
var check = false;
/* if something is still spinning */
if($('.timeline .activity i').hasClass('fa-spin'))
check = true;
return check;
}
function checkNewActivity(runs) {
$.ajax({
type: 'GET',
url: $('a[href="#activity"]').attr('data-activity-url'),
data: {'show_all': show_all},
success: function(data) {
var new_activity_hash = (data.activities + "").hashCode();
if(new_activity_hash != activity_hash) {
$("#activity-refresh").html(data.activities);
}
activity_hash = new_activity_hash;
$("#ops").html(data.ops);
$("#disk-ops").html(data.disk_ops);
$("[title]").tooltip();
/* changing the status text */
var icon = $("#vm-details-state i");
if(data.is_new_state) {
if(!icon.hasClass("fa-spin"))
icon.prop("class", "fa fa-spinner fa-spin");
} else {
icon.prop("class", "fa " + data.icon);
}
var vm_state = $("#vm-details-state");
if (vm_state.length) {
vm_state.data("status", data['status']);
$("#vm-details-state span").html(data['human_readable_status'].toUpperCase());
}
if(data['status'] == "RUNNING") {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").removeClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "pill").attr("href", "#console").parent("li").removeClass("disabled");
} else {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").addClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "_pill").attr("href", "#").parent("li").addClass("disabled");
}
if(data.status == "STOPPED" || data.status == "PENDING") {
$(".change-resources-button").prop("disabled", false);
$(".change-resources-help").hide();
} else {
$(".change-resources-button").prop("disabled", true);
$(".change-resources-help").show();
}
if(runs > 0 && decideActivityRefresh()) {
setTimeout(
function() {checkNewActivity(runs + 1);},
1000 + Math.exp(runs * 0.05)
);
} else {
in_progress = false;
if(reload_vm_detail) location.reload();
}
$('a[href="#activity"] i').removeClass('fa-spin');
},
error: function() {
in_progress = false;
}
});
}
}); });
String.prototype.hashCode = function() {
var hash = 0, i, chr, len;
if (this.length == 0) return hash;
for (i = 0, len = this.length; i < len; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
...@@ -90,8 +90,11 @@ html { ...@@ -90,8 +90,11 @@ html {
} }
.list-group .list-group-footer { .list-group .list-group-footer {
padding-top: 5px; height: 41px;
padding-bottom: 5px; }
.list-group-footer .text-right {
padding-top: 4px;
} }
.big { .big {
...@@ -199,7 +202,7 @@ html { ...@@ -199,7 +202,7 @@ html {
} }
.dashboard-index .panel { .dashboard-index .panel {
height: 300px; height: 294px;
} }
#vm-details-rename, #vm-details-h1-name, #vm-details-rename , #vm-details-rename, #vm-details-h1-name, #vm-details-rename ,
...@@ -586,8 +589,8 @@ footer a, footer a:hover, footer a:visited { ...@@ -586,8 +589,8 @@ footer a, footer a:hover, footer a:visited {
} }
#dashboard-vm-list, #dashboard-node-list, #dashboard-group-list, #dashboard-vm-list, #dashboard-node-list, #dashboard-group-list,
#dashboard-template-list { #dashboard-template-list, #dashboard-files-toplist {
min-height: 204px; min-height: 200px;
} }
#group-detail-user-table td:first-child, #group-detail-user-table th:last-child, #group-detail-user-table td:first-child, #group-detail-user-table th:last-child,
...@@ -749,10 +752,6 @@ textarea[name="new_members"] { ...@@ -749,10 +752,6 @@ textarea[name="new_members"] {
margin-top: 8px; margin-top: 8px;
} }
#dashboard-files-toplist {
min-height: 204px;
}
#dashboard-files-toplist div.list-group-item { #dashboard-files-toplist div.list-group-item {
color: #555; color: #555;
} }
...@@ -957,6 +956,11 @@ textarea[name="new_members"] { ...@@ -957,6 +956,11 @@ textarea[name="new_members"] {
#vm-list-search, #vm-mass-ops { #vm-list-search, #vm-mass-ops {
margin-top: 8px; margin-top: 8px;
} }
.list-group-item {
border-bottom: 0px !important;
}
.list-group-item-last { .list-group-item-last {
border-bottom: 1px solid #ddd !important; border-bottom: 1px solid #ddd !important;
} }
......
...@@ -28,39 +28,3 @@ ...@@ -28,39 +28,3 @@
$(".group-details-help-button").click(function() { $(".group-details-help-button").click(function() {
$(".group-details-help").stop().slideToggle(); $(".group-details-help").stop().slideToggle();
}); });
/* for Node removes buttons */
$('.delete-from-group').click(function() {
var href = $(this).attr('href');
var tr = $(this).closest('tr');
var group = $(this).data('group_pk');
var member = $(this).data('member_pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(removeMember,
{ 'url': href,
'data': [],
'tr': tr,
'group_pk': group,
'member_pk': member,
'type': "user",
'redirect': dir});
return false;
});
function removeMember(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
data.tr.fadeOut(function() {
$(this).remove();});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
$(function() { $(function() {
/* rename */ /* rename */
$("#group-list-rename-button, .group-details-rename-button").click(function() { $("#group-list-rename-button, .group-details-rename-button").click(function() {
$("#group-list-column-name", $(this).closest("tr")).hide(); $(".group-list-column-name", $(this).closest("tr")).hide();
$("#group-list-rename", $(this).closest("tr")).css('display', 'inline'); $("#group-list-rename", $(this).closest("tr")).css('display', 'inline');
$("#group-list-rename").find("input").select(); $("#group-list-rename").find("input").select();
}); });
...@@ -10,7 +10,7 @@ $(function() { ...@@ -10,7 +10,7 @@ $(function() {
$('.group-list-rename-submit').click(function() { $('.group-list-rename-submit').click(function() {
var row = $(this).closest("tr"); var row = $(this).closest("tr");
var name = $('#group-list-rename-name', row).val(); var name = $('#group-list-rename-name', row).val();
var url = '/dashboard/group/' + row.children("td:first-child").text().replace(" ", "") + '/'; var url = row.find(".group-list-column-name a").prop("href");
$.ajax({ $.ajax({
method: 'POST', method: 'POST',
url: url, url: url,
...@@ -18,7 +18,7 @@ $(function() { ...@@ -18,7 +18,7 @@ $(function() {
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) { success: function(data, textStatus, xhr) {
$("#group-list-column-name", row).html( $(".group-list-column-name", row).html(
$("<a/>", { $("<a/>", {
'class': "real-link", 'class': "real-link",
href: "/dashboard/group/" + data.group_pk + "/", href: "/dashboard/group/" + data.group_pk + "/",
......
$(function() {
nodeCreateLoaded();
});
function nodeCreateLoaded() {
/* no js compatibility */
$('.no-js-hidden').show();
$('.js-hidden').hide();
}
...@@ -30,20 +30,6 @@ $(function() { ...@@ -30,20 +30,6 @@ $(function() {
$(".node-details-help").stop().slideToggle(); $(".node-details-help").stop().slideToggle();
}); });
/* for Node removes buttons */
$('.node-enable').click(function() {
var node_pk = $(this).data('node-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(changeNodeStatus,
{ 'url': '/dashboard/node/status/' + node_pk + '/',
'data': [],
'pk': node_pk,
'type': "node",
'redirect': dir});
return false;
});
// remove trait // remove trait
$('.node-details-remove-trait').click(function() { $('.node-details-remove-trait').click(function() {
var to_remove = $(this).data("trait-pk"); var to_remove = $(this).data("trait-pk");
...@@ -69,22 +55,3 @@ $(function() { ...@@ -69,22 +55,3 @@ $(function() {
}); });
}); });
function changeNodeStatus(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
if(!data.redirect) {
selected = [];
addMessage(re.message, 'success');
} else {
window.location.replace('/dashboard');
}
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
...@@ -9,49 +9,4 @@ $(function() { ...@@ -9,49 +9,4 @@ $(function() {
$('.false').closest("tr").addClass('danger'); $('.false').closest("tr").addClass('danger');
$('.true').closest("tr").removeClass('danger'); $('.true').closest("tr").removeClass('danger');
} }
function statuschangeSuccess(tr){
var tspan=tr.children('.enabled').children();
var buttons=tr.children('.actions').children('.btn-group').children('.dropdown-menu').children('li').children('.node-enable');
buttons.each(function(index){
if ($(this).css("display")=="block"){
$(this).css("display","none");
}
else{
$(this).css("display","block");
}
});
if(tspan.hasClass("false")){
tspan.removeClass("false");
tspan.addClass("true");
tspan.text("✔");
}
else{
tspan.removeClass("true");
tspan.addClass("false");
tspan.text("✘");
}
colortable();
}
$('#table_container').on('click','.node-enable',function() {
var tr= $(this).closest("tr");
var pk =$(this).attr('data-node-pk');
var url = $(this).attr('href');
$.ajax({
method: 'POST',
url: url,
data: {'change_status':''},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
statuschangeSuccess(tr);
},
error: function(xhr, textStatus, error) {
addMessage("Error!", "danger");
}
});
return false;
});
}); });
$(function() { $(function() {
/* for template removes buttons */
$('.template-delete').click(function() {
var template_pk = $(this).data('template-pk');
addModalConfirmationOrDisplayMessage(deleteTemplate,
{ 'url': '/dashboard/template/delete/' + template_pk + '/',
'data': [],
'template_pk': template_pk,
});
return false;
});
/* for lease removes buttons */
$('.lease-delete').click(function() {
var lease_pk = $(this).data('lease-pk');
addModalConfirmationOrDisplayMessage(deleteLease,
{ 'url': '/dashboard/lease/delete/' + lease_pk + '/',
'data': [],
'lease_pk': lease_pk,
});
return false;
});
/* template table sort */ /* template table sort */
var ttable = $(".template-list-table").stupidtable(); var ttable = $(".template-list-table").stupidtable();
...@@ -43,67 +21,3 @@ $(function() { ...@@ -43,67 +21,3 @@ $(function() {
event.preventDefault(); event.preventDefault();
}); });
}); });
// send POST request then delete the row in table
function deleteTemplate(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
addMessage(re.message, 'success');
$('a[data-template-pk="' + data.template_pk + '"]').closest('tr').fadeOut(function() {
$(this).remove();
});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
// send POST request then delete the row in table
function deleteLease(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
addMessage(re.message, 'success');
$('a[data-lease-pk="' + data.lease_pk + '"]').closest('tr').fadeOut(function() {
$(this).remove();
});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
function addModalConfirmationOrDisplayMessage(func, data) {
$.ajax({
type: 'GET',
url: data['url'],
data: jQuery.param(data['data']),
success: function(result) {
$('body').append(result);
$('#confirmation-modal').modal('show');
$('#confirmation-modal').on('hidden.bs.modal', function() {
$('#confirmation-modal').remove();
});
$('#confirmation-modal-button').click(function() {
func(data);
$('#confirmation-modal').modal('hide');
});
},
error: function(xhr, textStatus, error) {
if(xhr.status === 403) {
addMessage(gettext("Only the owners can delete the selected object."), "warning");
} else {
addMessage(gettext("An error occurred. (") + xhr.status + ")", 'danger')
}
}
});
}
...@@ -20,15 +20,15 @@ function vmCreateLoaded() { ...@@ -20,15 +20,15 @@ function vmCreateLoaded() {
var template = $(this).data("template-pk"); var template = $(this).data("template-pk");
$.get("/dashboard/vm/create/?template=" + template, function(data) { $.get("/dashboard/vm/create/?template=" + template, function(data) {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data); $('body').append(data);
vmCreateLoaded(); vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); $('#confirmation-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() { $('#confirmation-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove(); $('#confirmation-modal').remove();
}); });
$("#create-modal").on("shown.bs.modal", function() { $("#confirmation-modal").on("shown.bs.modal", function() {
setDefaultSliderValues(); setDefaultSliderValues();
}); });
}); });
...@@ -48,18 +48,18 @@ function vmCreateLoaded() { ...@@ -48,18 +48,18 @@ function vmCreateLoaded() {
window.location.replace(data.redirect + '#activity'); window.location.replace(data.redirect + '#activity');
} }
else { else {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data); $('body').append(data);
vmCreateLoaded(); vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); $('#confirmation-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() { $('#confirmation-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove(); $('#confirmation-modal').remove();
}); });
} }
}, },
error: function(xhr, textStatus, error) { error: function(xhr, textStatus, error) {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
if (xhr.status == 500) { if (xhr.status == 500) {
addMessage("500 Internal Server Error", "danger"); addMessage("500 Internal Server Error", "danger");
...@@ -211,7 +211,7 @@ function vmCustomizeLoaded() { ...@@ -211,7 +211,7 @@ function vmCustomizeLoaded() {
}); });
/* start vm button clicks */ /* start vm button clicks */
$('#vm-create-customized-start').click(function() { $('#confirmation-modal #vm-create-customized-start').click(function() {
var error = false; var error = false;
$(".cpu-count-input, .ram-input, #id_name, #id_amount ").each(function() { $(".cpu-count-input, .ram-input, #id_name, #id_amount ").each(function() {
if(!$(this)[0].checkValidity()) { if(!$(this)[0].checkValidity()) {
...@@ -222,8 +222,6 @@ function vmCustomizeLoaded() { ...@@ -222,8 +222,6 @@ function vmCustomizeLoaded() {
$(this).find("i").prop("class", "fa fa-spinner fa-spin"); $(this).find("i").prop("class", "fa fa-spinner fa-spin");
if($("#create-modal")) return true;
$.ajax({ $.ajax({
url: '/dashboard/vm/create/', url: '/dashboard/vm/create/',
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
...@@ -238,18 +236,18 @@ function vmCustomizeLoaded() { ...@@ -238,18 +236,18 @@ function vmCustomizeLoaded() {
window.location.href = data.redirect + '#activity'; window.location.href = data.redirect + '#activity';
} }
else { else {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data); $('body').append(data);
vmCreateLoaded(); vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); $('#confirmation-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() { $('#confirmation-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove(); $('#confirmation-modal').remove();
}); });
} }
}, },