Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions cyder/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,10 +459,10 @@ def table_update(request, pk, obj_type=None):

Klass, FormKlass = get_klasses(obj_type)
obj = get_object_or_404(Klass, pk=pk)

if not perm_soft(request, ACTION_UPDATE, obj=obj):
return HttpResponse(json.dumps({'error': 'You do not have appropriate'
' permissions.'}))
return HttpResponse(json.dumps({
'error': {'__all__': [u'You do not have'
' appropriate permissions.']}}))

# DNS specific.
qd = request.POST.copy()
Expand All @@ -472,11 +472,22 @@ def table_update(request, pk, obj_type=None):
# Call prune tree later if error, else domain leak.
label, domain = ensure_label_domain(fqdn)
except ValidationError, e:
return HttpResponse(json.dumps({'error': e.messages}))
return HttpResponse(
json.dumps({'error': {'__all__': [e.messages]}}))
qd['label'], qd['domain'] = label, str(domain.pk)

form = FormKlass(qd, instance=obj)
# Set the fields that weren't modified
for key in form.fields:
if key not in qd:
old_value = form.initial[key]
if isinstance(old_value, list):
# ManyToManyFields need special treatment
form.data.setlist(key, old_value)
else:
form.data[key] = old_value

if form.is_valid():
form.save()
return HttpResponse()
return HttpResponse(json.dumps({'error': form.errors}))
return HttpResponse(json.dumps({'error': (form.errors)}))
2 changes: 1 addition & 1 deletion cyder/cydhcp/vlan/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def details(self):
"""For tables."""
data = super(Vlan, self).details()
data['data'] = [
('Name', 'name', self),
('Name', 'name', self.name),
('Number', 'number', self.number),
]
return data
Expand Down
2 changes: 1 addition & 1 deletion cyder/templates/base/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<div class="spreadsheet-mode hidden">
Click table cells below to directly modify data |
<a href="{{ request.path }}" class="exit-spreadsheet">
Exit spreadsheet mode
Discard Changes?
</a>
</div>
</div>
Expand Down
89 changes: 80 additions & 9 deletions media/js/tables.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
function cleanTablesForEditableGrid() {
// Remove Action column.
if ($('th:contains("Actions")')) {
$('th:contains("Actions")').remove();
$('td:last-child').remove();
if ($('.actions_column')) {
$('.actions_column').remove();
}

// Remove Info column.
if ($('th:contains("Info")')) {
$('th:contains("Info")').remove();
$('td:first-child').remove();
if ($('.info_column')) {
$('.info_column').remove();
}

// Strip links and paragraph tags, remove table cell markdown until
Expand Down Expand Up @@ -40,36 +38,109 @@ function editableGridCallback(rowIndex, columnIndex, oldValue, newValue, row) {
}


function enableEditableGrid() {
function enableEditableGrid( allPostData ) {
var $eg = $('#eg');
var csrfToken = $('#view-metadata').attr('data-csrfToken');
if (!$eg) {
return;
}

cleanTablesForEditableGrid();
editableGrid = new EditableGrid("My Editable Grid");
editableGrid.loadJSONFromString($eg.attr('data-metadata'));
editableGrid.modelChanged = editableGridCallback;
editableGrid.modelChanged = function(rowIndex, columnIndex, oldValue, newValue, row) {
/*
Callback function on change. Send whatever was changed so the change
can be validated and the object can be updated.
*/
var postData = {};
var data = {};
postData[editableGrid.getColumnName(columnIndex)] = newValue;
postData['csrfmiddlewaretoken'] = csrfToken;
data['row'] = row;
data['postData'] = postData;
data['url'] = $(row).attr('data-url');
data['oldValue'] = oldValue;
data['newValue'] = newValue;
allPostData[rowIndex + '-' + columnIndex] = data;
};
editableGrid.attachToHTMLTable('egtable');
editableGrid.renderGrid();
}


$(document).ready(function() {
$.ajaxSetup({async:false});
var allPostData = {};
var $enableEg = $('#enable-eg');
if ($enableEg.length) {
$enableEg[0].reset();

$('.exit-spreadsheet').click( function(e) {
e.preventDefault();
if (confirm('Are you sure you want to exit spreadsheet mode? ' +
'Your changes will not be submitted')) {
location.reload();
};
});

// Enable editable grid on checkbox.
$enableEg.find('input').removeAttr('disabled').change(function() {
$this = $(this);
if ($this.attr('checked')) {
enableEditableGrid();
enableEditableGrid(allPostData);
$this.attr('disabled', true);
}

$('#enable-eg').remove();
$('.spreadsheet-mode').show();
$('#action-bar').find('a').each(function() {
$(this).css('display', 'none')
});
$('#action-bar').append('<a id="eg_submit" class="btn" href="#">Submit</a>');
$('#eg_submit').click( function() {
var confirm_str = "Are you sure you want to make the following changes?\n";
jQuery.each(allPostData, function(i, data) {
confirm_str += data.oldValue + " -> " + data.newValue + "\n";
});
if (confirm(confirm_str)) {
$('.errors').each(function() {
$(this).remove();
});
var successIndex = [];
var success = true;
jQuery.each(allPostData, function(key, data) {
$.post(data.url, data.postData, function(resp) {
if (resp && resp.error) {
jQuery.each(resp.error, function(field, error) {
if (field == '__all__') {
$(data.row).after(
'<tr class="errors"><td><font '
+ 'color="red">' + error +
'</font></td></tr>');
} else {
field = $(data.row).find(
'.' + field + '_column');
field.append(
'<font class="errors" color="red"> '
+ error + '</font>');
};
});
success = false;
} else {
successIndex.push(key);
};
}, 'json');
});
if (success) {
location.reload();
} else {
jQuery.each(successIndex, function(index, key) {
delete allPostData[key];
});
};
};
});
});
}
});