* Finished create/edit methods

* Added delete method
* a little more refactoring ( ofc :-) )
Need to debug a bit more this, and probably make some adaptions for models that do not serializes objects
This commit is contained in:
Adolfo Gómez 2013-11-26 03:42:46 +00:00
parent 63da672f30
commit fa2335efd4
7 changed files with 146 additions and 71 deletions

View File

@ -34,6 +34,7 @@ from __future__ import unicode_literals
from handlers import NotFound, RequestError
from django.utils.translation import ugettext as _
from django.db import IntegrityError
import logging
@ -67,6 +68,12 @@ class ModelHandlerMixin(object):
model = None
save_fields = []
def __fillIntanceFields(self, item, res):
if hasattr(item, 'getInstance'):
for key, value in item.getInstance().valuesDict().iteritems():
value = {"true":True, "false":False}.get(value, value)
logger.debug('{0} = {1}'.format(key, value))
res[key] = value
def item_as_dict(self, item):
pass
@ -96,9 +103,7 @@ class ModelHandlerMixin(object):
result = []
for val in self.model.objects.all():
res = self.item_as_dict(val)
if hasattr(val, 'getInstance'):
for key, value in val.getInstance().valuesDict().iteritems():
res[key] = value
self.__fillIntanceFields(val, res)
result.append(res)
return result
@ -109,13 +114,10 @@ class ModelHandlerMixin(object):
if self.detail is not None and len(self._args) > 1:
return self.processDetail()
try:
val = self.model.objects.get(pk=self._args[0])
res = self.item_as_dict(val)
if hasattr(val, 'getInstance'):
for key, value in val.getInstance().valuesDict().iteritems():
res[key] = value
self.__fillIntanceFields(val, res)
return res
except:
raise NotFound('item not found')
@ -130,45 +132,48 @@ class ModelHandlerMixin(object):
except KeyError as e:
raise RequestError('needed parameter not found in data {0}'.format(unicode(e)))
if len(args) == 0: # create new
isNew = False
try:
if len(self._args) == 0: # create new
item = self.model.objects.create(**args);
res = self.item_as_dict(item)
except: # Duplicate key probably
raise RequestError('Element already exists (duplicate key error)')
elif len(args) == 1:
try:
elif len(self._args) == 1:
# We have to take care with this case, update will efectively update records on db
item = self.model.objects.get(pk=self._args[0]);
# Update "general" values
item.update(**args)
res = self.item_as_dict(item)
except:
raise RequestError('Element {0} do not exists anymore'.format(self._args[0]))
item.__dict__.update(args) # Update fields from args
else:
raise Exception() # Incorrect invocation
except self.model.DoesNotExist:
raise NotFound('Element do not exists')
except IntegrityError: # Duplicate key probably
raise RequestError('Element already exists (duplicate key error)')
except Exception as e:
raise RequestError('incorrect invocation to PUT')
try:
isNew = True
# Store associated object if needed
if self._params.has_key('data_type'): # Needs to store instance
item.data_type = self._params['data_type']
item.data = item.getInstance(self._params).serialize()
for key, value in item.getInstance().valuesDict().iteritems():
res[key] = value
res = self.item_as_dict(item)
self.__fillIntanceFields(item, res)
item.save()
except Exception as e:
item.delete() # Remove pre-saved element
raise RequestError(unicode(e))
return res
def delete(self):
logger.debug('method DELETE for {0}, {1}'.format(self.__class__.__name__, self._args))
if len(self._args) != 1:
raise RequestError('Delete need an argument')
raise RequestError('Delete need one and only one argument')
try:
item = self.model.objects.get(pk=self._args[0]);
item.delete()
except self.model.DoesNotExist:
raise NotFound('Element do not exists')
except Exception as e:
logger.exception('delete')
raise RequestError('incorrect invocation to DELETE')
return 'deleted'
class ModelTypeHandlerMixin(object):

View File

@ -96,7 +96,35 @@
request.setRequestHeader(api.config.auth_header, api.config.token);
},
});
};
}; // End putJson
api.deleteJson = function(path, options) {
options = options || {};
var success_fnc = options.success || function(){};
var fail_fnc = options.fail || api.defaultFail;
var url = api.url_for(path);
api.doLog('Ajax DELETE Json for "' + url + '"');
$.ajax({
url : url,
type : "DELETE",
dataType : "json",
success: function(data) {
api.doLog('Success on DELETE "' + url + '".');
api.doLog('Received ', data);
success_fnc(data);
},
error: function(jqXHR, textStatus, errorThrown) {
api.doLog('Error on DELETE "' + url + '". ', textStatus, ', ', errorThrown);
fail_fnc(jqXHR, textStatus, errorThrown);
},
beforeSend : function(request) {
request.setRequestHeader(api.config.auth_header, api.config.token);
},
});
}; // End putJson
// Public attributes
api.debug = true;
@ -142,6 +170,7 @@ function BasicModelRest(path, options) {
this.path = path;
this.getPath = options.getPath || path;
this.putPath = options.putPath || path;
this.delPath = options.delPath || path;
this.typesPath = options.typesPath || (path + '/types');
this.tableInfoPath = options.tableInfoPath || (path + '/tableinfo');
this.cache = api.cache('bmr'+path);
@ -254,6 +283,20 @@ BasicModelRest.prototype = {
});
},
// --------------
// Delete
// --------------
del: function(id, success_fnc, fail_fnc) {
"use strict";
var path = this.delPath + '/' + id;
api.deleteJson(path, {
success: success_fnc,
fail: fail_fnc
});
},
// --------------
// Types methods
// --------------

View File

@ -139,15 +139,22 @@ gui.connectivity.link = function(event) {
}));
gui.connectivity.transports.table({
rowSelect : 'multi',
rowSelect : 'single',
container : 'transports-placeholder',
buttons : [ 'new', 'edit', 'delete', 'xls' ],
onEdit: function(value, event, table) {
onEdit: function(value, event, table, refreshFnc) {
gui.connectivity.transports.rest.gui(value.type, function(itemGui){
gui.connectivity.transports.rest.item(value.id, function(item) {
var form = gui.fields(itemGui, item);
gui.launchModalForm(gettext('Edit transport')+' '+value.name,form, function(form_selector) {
var fields = gui.fields.read(form_selector);
var form = gui.form.fromFields(itemGui, item);
gui.launchModalForm(gettext('Edit transport')+' '+value.name,form, function(form_selector, closeFnc) {
var fields = gui.form.read(form_selector);
fields.data_type = value.type;
fields.nets_positive = false;
gui.connectivity.transports.rest.save(fields, function(data) { // Success on put
closeFnc();
refreshFnc();
}, gui.failRequestModalFnc(gettext('Error creating transport')) // Fail on put, show modal message
);
return false;
});
});
@ -155,9 +162,9 @@ gui.connectivity.link = function(event) {
},
onNew: function(type, table, refreshFnc) {
gui.connectivity.transports.rest.gui(type, function(itemGui) {
var form = gui.fields(itemGui);
var form = gui.form.fromFields(itemGui);
gui.launchModalForm(gettext('New transport'), form, function(form_selector, closeFnc) {
var fields = gui.fields.read(form_selector);
var fields = gui.form.read(form_selector);
// Append "own" fields, in this case data_type
fields.data_type = type;
fields.nets_positive = false;
@ -169,6 +176,13 @@ gui.connectivity.link = function(event) {
});
});
},
onDelete: function(value, event, table, refreshFnc) {
// TODO: Add confirmation to deletion
gui.connectivity.transports.rest.del(value.id, function(){
refreshFnc();
}, gui.failRequestModalFnc(gettext('Error removing transport'))
);
},
});
gui.connectivity.networks.table({
rowSelect : 'multi',

View File

@ -19,12 +19,12 @@ GuiElement.prototype = {
init : function() {
"use strict";
gui.doLog('Initializing ' + this.name);
var $this = this;
var self = this;
this.rest.types(function(data) {
var styles = '';
$.each(data, function(index, value) {
var className = $this.name + '-' + value.type;
$this.types[value.type] = {
var className = self.name + '-' + value.type;
self.types[value.type] = {
css : className,
name : value.name || '',
description : value.description || ''
@ -78,7 +78,7 @@ GuiElement.prototype = {
options = options || {};
gui.doLog('Composing table for ' + this.name);
var tableId = this.name + '-table';
var $this = this; // Store this for child functions
var self = this; // Store this for child functions
// ---------------
// Cells renderers
@ -101,7 +101,7 @@ GuiElement.prototype = {
// Icon renderer, based on type (created on init methods in styles)
var renderTypeIcon = function(data, type, value){
if( type == 'display' ) {
var css = $this.types[value.type].css;
var css = self.types[value.type].css;
return '<span class="' + css + '"></span> ' + renderEmptyCell(data);
} else {
return renderEmptyCell(data);
@ -185,7 +185,7 @@ GuiElement.prototype = {
columns: columns,
})).appendTo('head');
$this.rest.overview(function(data) { // Gets "overview" data for table (table contents, but resume form)
self.rest.overview(function(data) { // Gets "overview" data for table (table contents, but resume form)
var table = gui.table(title, tableId);
if (options.container === undefined) {
gui.appendToWorkspace('<div class="row"><div class="col-lg-12">' + table.text + '</div></div>');
@ -205,11 +205,11 @@ GuiElement.prototype = {
if( data.length > 1000 )
api.tools.blockUI();
$this.rest.overview(function(data) { // Restore overview
self.rest.overview(function(data) { // Restore overview
setTimeout( function() {
tbl.fnClearTable();
tbl.fnAddData(data);
onRefresh($this);
onRefresh(self);
api.tools.unblockUI();
}, 0);
}); // End restore overview
@ -257,7 +257,7 @@ GuiElement.prototype = {
var btn;
switch (value) {
case 'new':
if(Object.keys($this.types).length === 0) {
if(Object.keys(self.types).length === 0) {
btn = {
"sExtends" : "text",
"sButtonText" : gui.config.dataTableButtons['new'].text,
@ -269,7 +269,7 @@ GuiElement.prototype = {
var newButtons = [];
// Order buttons by name, much more easy for users... :-)
var order = [];
$.each($this.types, function(k, v){
$.each(self.types, function(k, v){
order.push({
type: k,
css: v.css,
@ -424,7 +424,7 @@ GuiElement.prototype = {
}
// if table rendered event
if( options.onLoad ) {
options.onLoad($this);
options.onLoad(self);
}
}); // End Overview data
}); // End Tableinfo data

View File

@ -3,11 +3,8 @@
"use strict";
// Returns a form that will manage a gui description (new or edit)
gui.fields = function(itemGui, item) {
var editing = item !== undefined; // Locate real Editing
item = item || {id:''};
var form = '<form class="form-horizontal" role="form">' +
'<input type="hidden" name="id" class="modal_field_data" value="' + item.id + '">';
gui.fieldsToHtml = function(itemGui, item, editing) {
var html = '';
// itemGui is expected to have fields sorted by .gui.order (REST api returns them sorted)
$.each(itemGui, function(index, f){
gui.doLog(f);
@ -16,7 +13,7 @@
if( f.gui.type == 'text' && f.gui.multiline ) {
f.gui.type = 'textbox';
}
form += api.templates.evaluate('tmpl_fld_'+f.gui.type, {
html += api.templates.evaluate('tmpl_fld_'+f.gui.type, {
value: item[f.name] || f.gui.value || f.gui.defvalue, // If no value present, use default value
values: f.gui.values,
label: f.gui.label,
@ -30,12 +27,27 @@
css: 'modal_field_data',
});
});
return html;
};
gui.form = {};
gui.form.fromFields = function(fields, item) {
var editing = item !== undefined; // Locate real Editing
item = item || {id:''};
var form = '<form class="form-horizontal" role="form">' +
'<input type="hidden" name="id" class="modal_field_data" value="' + item.id + '">';
if( fields.tabs ) {
} else {
form += gui.fieldsToHtml(fields, item, editing);
}
form += '</form>';
return form;
};
// Reads fields from a form
gui.fields.read = function(formSelector) {
gui.form.read = function(formSelector) {
var res = {};
$(formSelector + ' .modal_field_data').each(function(i, field) {
var $field = $(field);
@ -51,5 +63,6 @@
return res;
};
}(window.gui = window.gui || {}, jQuery));

View File

@ -112,15 +112,15 @@
gui.appendToWorkspace(gui.modal(id, title, content, actionButton, closeButton));
id = '#' + id; // for jQuery
$(id).modal({keyboard: false})
$(id).modal()
.on('hidden.bs.modal', function () {
$(id).remove();
});
};
gui.launchModalForm = function(title, content, onSuccess) {
gui.launchModalForm = function(title, form, onSuccess) {
var id = Math.random().toString().split('.')[1]; // Get a random ID for this modal
gui.appendToWorkspace(gui.modal(id, title, content));
gui.appendToWorkspace(gui.modal(id, title, form));
id = '#' + id; // for jQuery
// Get form

View File

@ -98,7 +98,7 @@
<script src="{% get_static_prefix %}adm/js/api-spreadsheet.js"></script>
<script src="{% get_static_prefix %}adm/js/gui.js"></script>
<script src="{% get_static_prefix %}adm/js/gui-fields.js"></script>
<script src="{% get_static_prefix %}adm/js/gui-form.js"></script>
<script src="{% get_static_prefix %}adm/js/gui-element.js"></script>
<!-- user interface management -->