Commit d5fe25eb by Oláh István Gergely

dashboard: node functions

parent a383b8e4
......@@ -91,6 +91,10 @@ body {
min-height: 20em;
}
#node-detail-panel .panel-body {
min-height: 20em;
}
:link i:before:hover {
text-decoration: none !important;
}
......@@ -142,19 +146,20 @@ body {
height: 300px;
}
#vm-details-rename, #vm-details-rename *, #vm-details-h1-name, #vm-list-rename, #vm-list-rename * {
#vm-details-rename, #vm-details-rename *, #vm-details-h1-name, #vm-list-rename, #vm-list-rename *,
#node-details-rename, #node-details-rename *, #node-details-h1-name, #node-list-rename, #node-list-rename * {
display: inline;
}
#vm-details-rename, #vm-list-rename {
#vm-details-rename, #vm-list-rename, #node-details-rename, #node-list-rename {
display: none;
}
#vm-details-rename-name {
#vm-details-rename-name, #node-details-rename-name {
max-width: 160px;
}
#vm-list-rename-name {
#vm-list-rename-name, #node-list-rename-name {
max-width: 100px;
}
......
......@@ -15,6 +15,23 @@ $(function () {
});
return false;
});
$('.node-create').click(function(e) {
$.ajax({
type: 'GET',
url: '/dashboard/node/create/',
success: function(data) {
$('body').append(data);
nodeCreateLoaded();
addSliderMiscs();
$('#node-create-modal').modal('show');
$('#node-create-modal').on('hidden.bs.modal', function() {
$('#node-create-modal').remove();
});
}
});
return false;
});
$('[href=#index-graph-view]').click(function (e) {
var box = $(this).data('index-box');
$("#" + box + "-list-view").hide();
......@@ -65,6 +82,20 @@ $(function () {
return false;
});
/* for Node removes buttons */
$('.node-delete').click(function() {
var node_pk = $(this).data('node-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(deleteNode,
{ 'url': '/dashboard/node/delete/' + node_pk + '/',
'data': [],
'node_pk': node_pk,
'redirect': dir});
return false;
});
});
function addSliderMiscs() {
......
$(function() {
if($('.timeline .activity:first i:first').hasClass('icon-spin'))
checkNewActivity();
/* save resources */
$('#vm-details-resources-save').click(function() {
$('i.icon-save', this).removeClass("icon-save").addClass("icon-refresh icon-spin");
$.ajax({
type: 'POST',
url: location.href,
data: $('#vm-details-resources-form').serialize(),
success: function(data, textStatus, xhr) {
addMessage(data['message'], 'success');
$("#vm-details-resources-save i").removeClass('icon-refresh icon-spin').addClass("icon-save");
},
error: function(xhr, textStatus, error) {
$("#vm-details-resources-save i").removeClass('icon-refresh icon-spin').addClass("icon-save");
addMessage("Eww, something is wrong", 'danger');
if (xhr.status == 500) {
// alert("uhuhuhuhuhuh");
} else {
// alert("unknown error");
}
}
});
return false;
});
/* rename */
$("#vm-details-h1-name, .vm-details-rename-button").click(function() {
$("#vm-details-h1-name").hide();
$("#vm-details-rename").css('display', 'inline');
});
/* rename ajax */
$('#vm-details-rename-submit').click(function() {
var name = $('#vm-details-rename-name').val();
$.ajax({
method: 'POST',
url: location.href,
data: {'new_name': name},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
$("#vm-details-h1-name").html(data['new_name']).show();
$('#vm-details-rename').hide();
// addMessage(data['message'], "success");
},
error: function(xhr, textStatus, error) {
addMessage("uhoh", "danger");
}
});
return false;
});
/* remove tag */
$('.vm-details-remove-tag').click(function() {
var to_remove = $.trim($(this).parent('div').text());
var clicked = $(this);
$.ajax({
type: 'POST',
url: location.href,
headers: {"X-CSRFToken": getCookie('csrftoken')},
data: {'to_remove': to_remove},
success: function(re) {
if(re['message'].toLowerCase() == "success") {
$(clicked).closest(".label").fadeOut(500, function() {
$(this).remove();
});
}
},
error: function() {
addMessage(re['message'], 'danger');
}
});
return false;
});
});
function checkNewActivity() {
var latest = $('.activity:first').data('activity-id');
var latest_sub = $('div[data-activity-id="' + latest + '"] .sub-timeline .sub-activity:first').data('activity-id');
var instance = location.href.split('/'); instance = instance[instance.length - 2];
$.ajax({
type: 'POST',
url: '/dashboard/vm/' + instance + '/activity/',
headers: {"X-CSRFToken": getCookie('csrftoken')},
data: {'latest': latest, 'latest_sub': latest_sub},
success: function(data) {
if(data['new_sub_activities'].length > 0) {
d = data['new_sub_activities'];
html = ""
for(var i=0; i<d.length; i++) {
html += '<div data-activity-id="' + d[i].id + '" class="sub-activity">' + d[i].name + ' - ';
if(d[i].finished != null) {
html += d[i].finished
} else {
html += '<i class="icon-refresh icon-spin" class="sub-activity-loading-icon"></i>';
}
html += '</div>';
}
$('div[data-activity-id="' + latest_sub + '"] .sub-activity .sub-activity-loading-icon').remove();
$('div[data-activity-id="' + latest + '"] .sub-timeline').prepend(html);
}
if(data['is_parent_finished']) {
var c = "icon-plus"
$('div[data-activity-id="' + latest + '"] .icon-refresh.icon-spin:first').removeClass('icon-refresh').removeClass('icon-spin').addClass(c);
}
if(data['latest_sub_finished'] != null) {
s = $('div[data-activity-id="' + latest_sub + '"]')
$('.icon-refresh.icon-spin', s).remove();
$(s).append(data['latest_sub_finished']);
}
if(data['is_parent_finished'])
return;
else
setTimeout(checkNewActivity, 1000);
},
error: function() {
}
});
}
......@@ -13,6 +13,7 @@ $(function() {
});
$('.node-list-table tbody').find('tr').mousedown(function() {
var retval = true;
if (ctrlDown) {
setRowColor($(this));
if(!$(this).hasClass('node-list-selected')) {
......@@ -20,6 +21,7 @@ $(function() {
} else {
selected.push($(this).index());
}
retval = false;
} else if(shiftDown) {
if(selected.length > 0) {
start = selected[selected.length - 1] + 1;
......@@ -36,6 +38,7 @@ $(function() {
}
}
}
retval = false;
} else {
$('.node-list-selected').removeClass('node-list-selected');
$(this).addClass('node-list-selected');
......@@ -53,10 +56,20 @@ $(function() {
} else {
$('.node-list-group-control a').attr('disabled', true);
}
return false;
return retval;
});
$(':not(#anything)').on('click', function (e) {
$('.node-list-details').each(function () {
//the 'is' for buttons that trigger popups
// //the 'has' for icons and other elements within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
return;
}
});
});
$('#node-list-group-migrate').click(function() {
console.log(collectIds(selected));
});
......@@ -64,12 +77,6 @@ $(function() {
$('.node-list-details').popover({
'placement': 'auto',
'html': true,
'trigger': 'hover'
});
$('.node-list-connect').popover({
'placement': 'left',
'html': true,
'trigger': 'click'
});
......@@ -80,11 +87,48 @@ $(function() {
$('tbody a').click(function(e) {
// browser doesn't jump to top when clicked the buttons
if(!$(this).hasClass('real-link')) {
if(!$(this).hasClass('real-link')) {
return false;
}
});
/* rename */
$("#node-list-rename-button, .node-details-rename-button").click(function() {
$("#node-list-column-name", $(this).closest("tr")).hide();
$("#node-list-rename", $(this).closest("tr")).css('display', 'inline');
});
/* rename ajax */
$('.node-list-rename-submit').click(function() {
var row = $(this).closest("tr")
var name = $('#node-list-rename-name', row).val();
var url = '/dashboard/node/' + row.children("td:first-child").text().replace(" ", "") + '/';
$.ajax({
method: 'POST',
url: url,
data: {'new_name': name},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
$("#node-list-column-name", row).html(
$("<a/>", {
'class': "real-link",
href: "/dashboard/node/" + data['node_pk'] + "/",
text: data['new_name']
})
).show();
$('#node-list-rename', row).hide();
// addMessage(data['message'], "success");
},
error: function(xhr, textStatus, error) {
addMessage("uhoh", "danger");
}
});
return false;
});
/* group actions */
/* select all */
......@@ -103,9 +147,15 @@ $(function() {
/* mass vm delete */
$('#node-list-group-delete').click(function() {
text = "Are you sure you want to delete the selected VMs?";
random_vm_pk = $('.vm-delete').eq(0).data('vm-pk');
addModalConfirmation(text, random_vm_pk, massDeleteVm, false);
addModalConfirmation(massDeleteVm,
{
'url': '/dashboard/node/mass-delete/',
'data': {
'selected': selected,
'v': collectIds(selected)
}
}
);
return false;
});
});
......@@ -114,16 +164,15 @@ function collectIds(rows) {
var ids = [];
for(var i = 0; i < rows.length; i++) {
var div = $('td:first-child div', $('.node-list-table tbody tr').eq(rows[i]));
ids.push(div.prop('id').replace('vm-', ''));
ids.push(div.prop('id').replace('node-', ''));
}
return ids;
}
function setRowColor(row) {
if(!row.hasClass('vm-list-selected')) {
if(!row.hasClass('node-list-selected')) {
row.addClass('node-list-selected');
} else {
row.removeClass('node-list-selected');
}
}
from django_tables2 import Table, A
from django_tables2.columns import LinkColumn, TemplateColumn, Column
from django_tables2.columns import LinkColumn, TemplateColumn, Column, BooleanColumn
from vm.models import Instance, Node
from django.utils.translation import ugettext_lazy as _
......@@ -46,17 +46,99 @@ class NodeListTable(Table):
pk = Column(
verbose_name="ID",
attrs={'th': {'class': 'node-list-table-thin'}},
)
name = LinkColumn(
'dashboard.views.node-detail',
args=[A('pk')],
attrs={'a': {'class': 'real-link'}}
overcommit = Column(
verbose_name="Overcommit",
attrs={'th': {'class': 'node-list-table-thin'}},
)
host = Column(
verbose_name="Host",
)
enabled = BooleanColumn(
verbose_name="Enabled",
attrs={'th': {'class': 'node-list-table-thin'}},
)
name = TemplateColumn(
template_name="dashboard/node-list/column-name.html"
)
priority = Column(
verbose_name=_("Priority"),
attrs={'th': {'class': 'node-list-table-thin'}},
)
number_of_VMs = TemplateColumn(
template_name='dashboard/node-list/column-vm.html',
attrs={'th': {'class': 'node-list-table-admin'}},
)
admin = TemplateColumn(
template_name='dashboard/node-list/column-admin.html',
attrs={'th': {'class': 'node-list-table-admin'}},
)
details = TemplateColumn(
template_name='dashboard/node-list/column-details.html',
attrs={'th': {'class': 'node-list-table-thin'}},
)
actions = TemplateColumn(
attrs={'th': {'class': 'node-list-table-thin'}},
template_code='{% include "dashboard/node-list/column-actions.html" with btn_size="btn-xs" %}',
# actions = TemplateColumn('{% load my_filters %}{{ record.name|int_to_time }}'
# attrs={'th': {'class': 'node-list-table-thin'},'extra_tag':},
)
# time_of_suspend = TemplateColumn(
# '{{ record.time_of_suspend|timeuntil }}',
# verbose_name=_("Suspend in"))
# time_of_delete = TemplateColumn(
# '{{ record.time_of_delete|timeuntil }}',
# verbose_name=_("Delete in"))
class Meta:
model = Node
attrs = {'class': ('table table-bordered table-striped table-hover '
'node-list-table')}
fields = ('pk', 'name', 'host', 'enabled', 'created', 'modified',
'priority', 'overcommit', )
fields = ('pk', 'name', 'host', 'enabled', 'priority', 'overcommit','number_of_VMs', )
class NodeVmListTable(Table):
pk = TemplateColumn(
template_name='dashboard/vm-list/column-id.html',
verbose_name="ID",
attrs={'th': {'class': 'vm-list-table-thin'}},
)
name = TemplateColumn(
template_name="dashboard/vm-list/column-name.html"
)
admin = TemplateColumn(
template_name='dashboard/vm-list/column-admin.html',
attrs={'th': {'class': 'vm-list-table-admin'}},
)
details = TemplateColumn(
template_name='dashboard/vm-list/column-details.html',
attrs={'th': {'class': 'vm-list-table-thin'}},
)
actions = TemplateColumn(
template_name='dashboard/vm-list/column-actions.html',
attrs={'th': {'class': 'vm-list-table-thin'}},
)
time_of_suspend = TemplateColumn(
'{{ record.time_of_suspend|timeuntil }}',
verbose_name=_("Suspend in"))
time_of_delete = TemplateColumn(
'{{ record.time_of_delete|timeuntil }}',
verbose_name=_("Delete in"))
class Meta:
model = Instance
attrs = {'class': ('table table-bordered table-striped table-hover '
'vm-list-table')}
fields = ('pk', 'name', 'state', 'time_of_suspend', 'time_of_delete', )
{% load i18n %}
<div class="panel panel-default">
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right toolbar">
<div class="btn-group">
<a href="#node-graph-view" class="btn btn-default btn-xs"><i class="icon-dashboard"></i></a>
<a href="#node-list-view" class="btn btn-default btn-xs"><i class="icon-list"></i></a>
<a href="#index-graph-view" data-index-box="node" class="btn btn-default btn-xs"><i class="icon-dashboard"></i></a>
<a href="#index-list-view" data-index-box="node" class="btn btn-default btn-xs disabled"><i class="icon-list"></i></a>
</div>
<span class="btn btn-default btn-xs infobtn" title="Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. "><i class="icon-info-sign"></i></span>
</div>
<h3 class="no-margin">
<i class="icon-sitemap"></i> {% trans "Compute nodes" %}
</h3>
</div >
<div class="list-group" id="node-list-view">
{% for i in nodes %}
<a href="{% url "dashboard.views.node-detail" pk=i.pk %}" class="list-group-item">
<i class="icon-{% if i.enabled == True %}play-sign{% else %}pause{% endif %}"></i> {{ i.name }} <div class="pull-right"><i class="icon-star text-primary" title="Mark as favorite."></i></div>
</a>
{% endfor %}
<div href="#" class="list-group-item list-group-footer">
<div class="row">
<div class="col-sm-6 col-xs-6 input-group input-group-sm">
<input type="text" class="form-control" placeholder="Search..." />
<div class="input-group-btn">
<button type="submit" class="form-control btn btn-primary" title="search"><i class="icon-search"></i></button>
</div>
</div>
<div class="col-sm-6 text-right">
{% if more_nodes > 0 %}
<a class="btn btn-primary btn-xs" href="{% url "dashboard.views.node-list" %}">
<i class="icon-chevron-sign-right"></i> <strong>{{ more_nodes }}</strong> more
</a>
{% endif %}
<a class="btn btn-success btn-xs node-create" href="{% url "dashboard.views.node-create" %}"><i class="icon-plus-sign"></i> new </a>
</div>
</div>
</div>
</div>
<div class="panel-body" id="node-graph-view" style="">
<p class="pull-right"> <input class="knob" data-fgColor="chartreuse" data-thickness=".4" data-width="60" data-height="60" data-readOnly="true" value="68"></p>
<p><span class="big"><big>13</big> running </span>
+ <big>3</big> off + <big>3</big> missing</p>
<div class="panel-body" id="node-graph-view" style="display: none">
<p class="pull-right"> <input class="knob" data-fgColor="chartreuse" data-thickness=".4" data-width="60" data-height="60" data-readOnly="true" value="{% widthratio node_num.running sum_node_num 100 %}"></p>
<p><span class="big"><big>{{ node_num.running }}</big> running </span>
+ <big>{{ node_num.missing }}</big> missing + <br><big>{{ node_num.disabled }}</big> disabled + <big>{{ node_num.offline }}</big> offline</p>
<ul class="list-inline">
{% for i in nodes %}
<li class="label label-success"><i class="icon-{% if i.enabled == True %}play-sign{% else %}pause{% endif %}"></i>{{ i.name }}</li>
{% for i in nodes %}
<a class="label {% if i.state == 'online' %}label-success{% elif i.state == 'missing' %}label-danger{% else %}label-warning{% endif %}" href="{% url "dashboard.views.node-detail" pk=i.pk %}"><i class="icon-{% if i.enabled == True %}play-sign{% else %}pause{% endif %}"></i> {{ i.name}}</a>
{% endfor %}
</ul>
......@@ -31,12 +58,12 @@
</div>
</div>
<div class="col-sm-6 text-right">
{% if more_nodes > 0 %}
{% if more_nodes >= 0 %}
<a class="btn btn-primary btn-xs" href="{% url "dashboard.views.node-list" %}">
<i class="icon-chevron-sign-right"></i> <strong>{{ more_nodes }}</strong> more
</a>
{% endif %}
<a class="btn btn-success btn-xs vm-create" href="{% url "dashboard.views.vm-create" %}"><i class="icon-plus-sign"></i> new </a>
<a class="btn btn-success btn-xs node-create" href="{% url "dashboard.views.node-create" %}"><i class="icon-plus-sign"></i> new </a>
</div>
</div>
</div>
......
......@@ -31,5 +31,6 @@
{% endblock %}
{% block extra_js %}
<script src="{{ STATIC_URL }}dashboard/vm-create.js"></script>
<script src="{{ STATIC_URL }}dashboard/vm-create.js"></script>
<script src="{{ STATIC_URL }}dashboard/node-create.js"></script>
{% endblock %}
......@@ -6,17 +6,6 @@
<form method="POST" action="/dashboard/vm/create/">
{% csrf_token %}
<div class="row">
<div class="col-sm-10">
<select class="select form-control" id="vm-create-template-select" name="template-pk">
<option value="-1">Choose a VM template</option>
{% for template in templates %}
<option value="{{ template.pk }}">{{ template.name}}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<div class="col-sm-5">
<a class="btn btn-info vm-create-advanced-btn">Advanced <i class="vm-create-advanced-icon icon-caret-down"></i></a>
</div>
......
......@@ -2,14 +2,21 @@
<form id="vm-details-resources-form" method="POST" action="">
{% csrf_token %}
<p class="row">
<div class="col-sm-3">
<label for="cpu-count-slider"><i class="icon-cogs"></i> {% trans "Name" %}</label>
</div>
<div class="col-sm-9">
<label > {{ node.name }} </label>
</div>
</p>
<dl class="dl-horizontal">
<dt>Name:</dt><dd>{{ node.name }}</dd>
<dt>Number of cores:</dt><dd>{{ node.num_cores }}</dd>
<dt>Memory:</dt> <dd>{% widthratio node.ram_size 1048576 1 %} MB</dd>
<dt>Architecture:</td><dd>{{ record.arch }}</dd>
<dt>IPv4 address:</dt><dd>{{ node.host.ipv4 }}</dd>
<dt>IPv6 address:</dt><dd> {{ node.host.ipv6 }}</dd>
<dt>Enabled:</dt><dd>{{ node.enabled }}</dd>
<dt>Host online:</dt><dd> {{ node.online }}</dd>
<dt>Priority:</dt><dd>{{ node.priority }}</dd>
<dt>Host owner:</dt><dd>{{ node.host.owner }}</dd>
<dt>Vlan:</dt><dd>{{ node.host.vlan }}</dd>
<dt>Hostname:</dt><dd>{{ node.host.hostname }}</dd>
</dl>
<p class="row">
<div class="col-sm-3">
......@@ -154,7 +161,7 @@
<label for="cpu-count-slider"><i class="icon-cogs"></i> {% trans "CPU count" %}</label>
</div>
<div class="col-sm-9">
<label > {{ node.host. }} </label>
<label > {{ node.host }} </label>
</div>
</p>
......
{% load render_table from django_tables2 %}
{% block content %}
<div class="panel-body">
{% render_table table %}
</div>
{% endblock %}
<script>
"use strict";
$('a[data-toggle$="pill"][href!="#virtualmachines"]').click(function() {
$("#node-info-pane").fadeIn();
$("#node-detail-pane").removeClass("col-md-12");
});
$('a[href$="virtualmachines"]').click(function() {
$("#node-info-pane").hide();
$("#node-detail-pane").addClass("col-md-12");
});
</script>
{% block extra_js %}
<script src="{{ STATIC_URL}}dashboard/vm-list.js"></script>
{% endblock %}
......@@ -7,22 +7,22 @@
<h1>{{ node.name }} <small>{{ node.get_connect_host }}</small></h1>
</div>
<div class="row">
<div class="col-md-4" id="vm-info-pane">
<div class="col-md-4" id="node-info-pane">
<div class="big">
<span class="label label-success">{{ node.enabled }}</span>
<div class="btn-group">
<button type="button" class="btn btn-warning dropdown-toggle" data-toggle="dropdown">Action <i class="icon-caret-down"></i></button>
<ul class="dropdown-menu" role="menu">
<li><a href="#"><i class="icon-refresh"></i> Flash</a></li>
<li><a href="#"><i class="icon-refresh"></i> Reboot</a></li>
<li><a href="#"><i class="icon-off"></i> Shutdown</a></li>
<li><a data-vm-pk="{{ node.pk }}" class="vm-delete" href="{% url "dashboard.views.delete-vm" pk=node.pk %}"><i class="icon-remove"></i> Discard</a></li>
</ul>
</div>
<span class="label {% if node.state == 'online' %}label-success
{% elif node.state == 'missing' %}label-danger
{% elif node.state == 'disabled' %}label-warning
{% elif node.state == 'offline' %}label-warning
{% endif %}">{{ node.state }}</span>
<div class="btn-group">
{% with node as record %}
{% include "dashboard/node-list/column-actions.html" with btn_size="" %}
{% endwith %}
</div>
</div>
</div>
<div class="col-md-8" id="vm-detail-pane">
<div class="panel panel-default" id="vm-detail-panel">
<div class="col-md-8" id="node-detail-pane">
<div class="panel panel-default" id="node-detail-panel">
<ul class="nav nav-pills panel-heading">
<li class="active">
<a href="#home" data-toggle="pill" class="text-center">
......@@ -33,16 +33,21 @@
<i class="icon-tasks icon-2x"></i><br>
{% trans "Resources" %}</a></li>
<li>
<a href="#virtualmachines" data-toggle="pill" class="text-center">
<i class="icon-desktop icon-2x"></i><br>
{% trans "Virtual Machines" %}</a></li>
<li>
<a href="#activity" data-toggle="pill" class="text-center">
<i class="icon-time icon-2x"></i><br>
{% trans "Activity" %}</a></li>
</ul>
</ul>
<div class="tab-content panel-body">
<div class="tab-pane active" id="home">{% include "dashboard/node-detail-home.html" %}</div>
<div class="tab-pane" id="resources">{% include "dashboard/node-detail-resources.html" %}</div>
<div class="tab-pane" id="activity">{% include "dashboard/node-detail-activity.html" %}</div>
</div>
<div class="tab-pane" id="virtualmachines">{% include "dashboard/node-detail-vm.html" %}</div>
</div>
</div>
</div>
</div>
......
<div class="btn-group">
<button type="button" class="btn btn-xs btn-warning dropdown-toggle" data-toggle="dropdown">Action <i class="icon-caret-down"></i></button>
<button type="button" class="btn {{ btn_size }} btn-warning dropdown-toggle" data-toggle="dropdown">Action <i class="icon-caret-down"></i></button>
<ul class="dropdown-menu" role="menu">
<li><a href="#"><i class="icon-refresh"></i> Reboot</a></li>
<li><a href="#"><i class="icon-off"></i> Shutdown</a></li>
<li><a data-node-pk="{{ record.pk }}" class="real-link node-delete" href="{% url "dashboard.views.delete-node" pk=record.pk %}?next={{ request.path }}"><i class="icon-remove"></i> Discard</a></li>
</ul>
<li><a href="#"><i class="icon-cloud-upload"></i> Flush</a></li>
{% if record.enabled %}
<li><a data-node-pk="{{ record.pk }}" class="real-link node-delete" href="{% url "dashboard.views.delete-node" pk=record.pk %}?next={{ request.path }}"><i class="icon-remove"></i> Disable</a></li>
{% else %}
<li><a data-node-pk="{{ record.pk }}" class="real-link node-delete" href="{% url "dashboard.views.delete-node" pk=record.pk %}?next={{ request.path }}"><i class="icon-check"></i> Enable</a></li>
{% endif%}
<li><a data-node-pk="{{ record.pk }}" class="real-link node-delete" href="{% url "dashboard.views.delete-node" pk=record.pk %}?next={{ request.path }}"><i class="icon-trash"></i> Delete</a></li>
</ul>
</div>