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 = {
"jquery-knob/dist/jquery.knob.min.js",
"jquery-simple-slider/js/simple-slider.js",
"dashboard/dashboard.js",
"dashboard/activity.js",
"dashboard/group-details.js",
"dashboard/group-list.js",
"dashboard/js/stupidtable.min.js", # no bower file
......
......@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None):
"in the 'target_cls' parameter to this "
"call.")
assert not hasattr(target_cls, op_id), (
"target class already has an attribute with this id")
if not issubclass(target_cls, OperatedMixin):
raise TypeError("%r is not a subclass of %r" %
(target_cls.__name__, OperatedMixin.__name__))
......
......@@ -898,7 +898,7 @@ class VmDownloadDiskForm(OperationForm):
def clean(self):
cleaned_data = super(VmDownloadDiskForm, self).clean()
if not cleaned_data['name']:
if cleaned_data['url']:
if cleaned_data.get('url'):
cleaned_data['name'] = urlparse(
cleaned_data['url']).path.split('/')[-1]
if not cleaned_data['name']:
......@@ -908,6 +908,36 @@ class VmDownloadDiskForm(OperationForm):
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):
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
......
/* for functions in both vm list and vm detail */
$(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) {
var icon = $(this).children("i").addClass('fa-spinner fa-spin');
......@@ -23,11 +48,9 @@ $(function() {
});
/* 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");
$(this).find("i").prop("class", "fa fa-fw fa-spinner fa-spin");
$.ajax({
url: url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
......@@ -79,4 +102,91 @@ $(function() {
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 {
}
.list-group .list-group-footer {
padding-top: 5px;
padding-bottom: 5px;
height: 41px;
}
.list-group-footer .text-right {
padding-top: 4px;
}
.big {
......@@ -199,7 +202,7 @@ html {
}
.dashboard-index .panel {
height: 300px;
height: 294px;
}
#vm-details-rename, #vm-details-h1-name, #vm-details-rename ,
......@@ -586,8 +589,8 @@ footer a, footer a:hover, footer a:visited {
}
#dashboard-vm-list, #dashboard-node-list, #dashboard-group-list,
#dashboard-template-list {
min-height: 204px;
#dashboard-template-list, #dashboard-files-toplist {
min-height: 200px;
}
#group-detail-user-table td:first-child, #group-detail-user-table th:last-child,
......@@ -749,10 +752,6 @@ textarea[name="new_members"] {
margin-top: 8px;
}
#dashboard-files-toplist {
min-height: 204px;
}
#dashboard-files-toplist div.list-group-item {
color: #555;
}
......@@ -957,6 +956,11 @@ textarea[name="new_members"] {
#vm-list-search, #vm-mass-ops {
margin-top: 8px;
}
.list-group-item {
border-bottom: 0px !important;
}
.list-group-item-last {
border-bottom: 1px solid #ddd !important;
}
......
......@@ -28,39 +28,3 @@
$(".group-details-help-button").click(function() {
$(".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() {
/* rename */
$("#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").find("input").select();
});
......@@ -10,7 +10,7 @@ $(function() {
$('.group-list-rename-submit').click(function() {
var row = $(this).closest("tr");
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({
method: 'POST',
url: url,
......@@ -18,7 +18,7 @@ $(function() {
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
$("#group-list-column-name", row).html(
$(".group-list-column-name", row).html(
$("<a/>", {
'class': "real-link",
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() {
$(".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
$('.node-details-remove-trait').click(function() {
var to_remove = $(this).data("trait-pk");
......@@ -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() {
$('.false').closest("tr").addClass('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() {
/* 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 */
var ttable = $(".template-list-table").stupidtable();
......@@ -43,67 +21,3 @@ $(function() {
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() {
var template = $(this).data("template-pk");
$.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);
vmCreateLoaded();
addSliderMiscs();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
$('#confirmation-modal').modal('show');
$('#confirmation-modal').on('hidden.bs.modal', function() {
$('#confirmation-modal').remove();
});
$("#create-modal").on("shown.bs.modal", function() {
$("#confirmation-modal").on("shown.bs.modal", function() {
setDefaultSliderValues();
});
});
......@@ -48,18 +48,18 @@ function vmCreateLoaded() {
window.location.replace(data.redirect + '#activity');
}
else {
var r = $('#create-modal'); r.next('div').remove(); r.remove();
var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data);
vmCreateLoaded();
addSliderMiscs();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
$('#confirmation-modal').modal('show');
$('#confirmation-modal').on('hidden.bs.modal', function() {
$('#confirmation-modal').remove();
});
}
},
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) {
addMessage("500 Internal Server Error", "danger");
......@@ -211,7 +211,7 @@ function vmCustomizeLoaded() {
});
/* start vm button clicks */
$('#vm-create-customized-start').click(function() {
$('#confirmation-modal #vm-create-customized-start').click(function() {
var error = false;
$(".cpu-count-input, .ram-input, #id_name, #id_amount ").each(function() {
if(!$(this)[0].checkValidity()) {
......@@ -222,8 +222,6 @@ function vmCustomizeLoaded() {
$(this).find("i").prop("class", "fa fa-spinner fa-spin");
if($("#create-modal")) return true;
$.ajax({
url: '/dashboard/vm/create/',
headers: {"X-CSRFToken": getCookie('csrftoken')},
......@@ -238,18 +236,18 @@ function vmCustomizeLoaded() {
window.location.href = data.redirect + '#activity';
}
else {
var r = $('#create-modal'); r.next('div').remove(); r.remove();
var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data);
vmCreateLoaded();
addSliderMiscs();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
$('#confirmation-modal').modal('show');
$('#confirmation-modal').on('hidden.bs.modal', function() {
$('#confirmation-modal').remove();
});
}
},
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) {
addMessage("500 Internal Server Error", "danger");
......
</
var show_all = false;
var in_progress = false;
var activity_hash = 5;
var Websock_native; // not sure
var reload_vm_detail = false;
$(function() {
/* do we need to check for new activities */
if(decideActivityRefresh()) {
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
}
$('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;
});
/* save resources */
$('#vm-details-resources-save').click(function(e) {
var error = false;
......@@ -43,7 +16,7 @@ $(function() {
var vm = $(this).data("vm");
$.ajax({
type: 'POST',
url: "/dashboard/vm/" + vm + "/op/resources_change/",
url: $(this).parent("form").prop('action'),
data: $('#vm-details-resources-form').serialize(),
success: function(data, textStatus, xhr) {
if(data.success) {
......@@ -89,17 +62,6 @@ $(function() {
return false;
});
/* remove port */
$('.vm-details-remove-port').click(function() {
addModalConfirmation(removePort,
{
'url': $(this).prop("href"),
'data': [],
'rule': $(this).data("rule")
});
return false;
});
/* for js fallback */
$("#vm-details-pw-show").parent("div").children("input").prop("type", "password");
......@@ -123,80 +85,6 @@ $(function() {
span.tooltip();
});
/* change password confirmation */
$("#vm-details-pw-change").click(function() {
$("#vm-details-pw-confirm").fadeIn();
return false;
});
/* change password */
$(".vm-details-pw-confirm-choice").click(function() {
choice = $(this).data("choice");
if(choice) {
pk = $(this).data("vm");
$.ajax({
type: 'POST',
url: "/dashboard/vm/" + pk + "/",
data: {'change_password': 'true'},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
location.reload();
},
error: function(xhr, textStatus, error) {
if (xhr.status == 500) {
addMessage("Internal Server Error", "danger");
} else {
addMessage(xhr.status + " Unknown Error", "danger");
}
}
});
} else {
$("#vm-details-pw-confirm").fadeOut();
}
return false;
});