forked from shaba/openuds
* 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:
parent
63da672f30
commit
fa2335efd4
@ -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):
|
||||
|
@ -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
|
||||
// --------------
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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 -->
|
||||
|
Loading…
Reference in New Issue
Block a user