forked from shaba/openuds
Advancing on table/model editing
More refactoring of code
This commit is contained in:
parent
c98e964bba
commit
043b28cfb4
@ -37,7 +37,7 @@ from django.views.decorators.csrf import csrf_exempt
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _, activate
|
||||
from django.conf import settings
|
||||
from handlers import Handler, HandlerError, AccessDenied, NotFound, RequestError
|
||||
from handlers import Handler, HandlerError, AccessDenied, NotFound, RequestError, ResponseError
|
||||
|
||||
import time
|
||||
import logging
|
||||
@ -150,6 +150,8 @@ class Dispatcher(View):
|
||||
return response
|
||||
except RequestError as e:
|
||||
return http.HttpResponseServerError(unicode(e))
|
||||
except ResponseError as e:
|
||||
return http.HttpResponseServerError(unicode(e))
|
||||
except AccessDenied as e:
|
||||
return http.HttpResponseForbidden(unicode(e))
|
||||
except NotFound as e:
|
||||
|
@ -54,6 +54,9 @@ class AccessDenied(HandlerError):
|
||||
class RequestError(HandlerError):
|
||||
pass
|
||||
|
||||
class ResponseError(HandlerError):
|
||||
pass
|
||||
|
||||
class Handler(object):
|
||||
raw = False # If true, Handler will return directly an HttpResponse Object
|
||||
name = None # If name is not used, name will be the class name in lower case
|
||||
@ -86,11 +89,8 @@ class Handler(object):
|
||||
if not self._session.has_key('REST'):
|
||||
raise Exception() # No valid session, so auth_token is also invalid
|
||||
except:
|
||||
if settings.DEBUG: # Right now all users are valid
|
||||
self.genAuthToken(-1, 'root', 'es', True, True)
|
||||
else:
|
||||
self._authToken = None
|
||||
self._session = None
|
||||
self._authToken = None
|
||||
self._session = None
|
||||
|
||||
if self._authToken is None:
|
||||
raise AccessDenied()
|
||||
|
@ -50,6 +50,7 @@ logger = logging.getLogger(__name__)
|
||||
class Authenticators(ModelHandler):
|
||||
model = Authenticator
|
||||
detail = { 'users': Users, 'groups':Groups }
|
||||
save_fields = ['name', 'comments']
|
||||
|
||||
table_title = _('Current authenticators')
|
||||
table_fields = [
|
||||
@ -63,7 +64,7 @@ class Authenticators(ModelHandler):
|
||||
|
||||
def getGui(self, type_):
|
||||
try:
|
||||
return auths.factory().lookup(type_).guiDescription()
|
||||
return self.addDefaultFields(auths.factory().lookup(type_).guiDescription(), ['name', 'comments'])
|
||||
except:
|
||||
raise NotFound('type not found')
|
||||
|
||||
|
@ -33,9 +33,9 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
from uds.models import Authenticator, User
|
||||
from uds.models import Authenticator
|
||||
|
||||
from uds.REST import Handler, HandlerError
|
||||
from uds.REST import Handler
|
||||
|
||||
import logging
|
||||
|
||||
|
@ -37,7 +37,7 @@ from django.utils.translation import ugettext as _
|
||||
from uds.core.Environment import Environment
|
||||
|
||||
from uds.REST.model import DetailHandler
|
||||
from uds.REST import NotFound
|
||||
from uds.REST import NotFound, ResponseError
|
||||
|
||||
import logging
|
||||
|
||||
@ -55,7 +55,8 @@ class Services(DetailHandler):
|
||||
'name': k.name,
|
||||
'comments': k.comments,
|
||||
'type': k.data_type,
|
||||
'typeName' : _(k.getType().name())
|
||||
'typeName' : _(k.getType().name()),
|
||||
'deployed_services_count' : k.deployedServices.count(),
|
||||
} for k in parent.services.all() ]
|
||||
else:
|
||||
with parent.get(pk=item) as k:
|
||||
@ -64,7 +65,8 @@ class Services(DetailHandler):
|
||||
'name': k.name,
|
||||
'comments': k.comments,
|
||||
'type': k.data_type,
|
||||
'typeName' : _(k.getType().name())
|
||||
'typeName' : _(k.getType().name()),
|
||||
'deployed_services_count' : k.deployedServices.count(),
|
||||
}
|
||||
except:
|
||||
logger.exception('En services')
|
||||
@ -80,7 +82,8 @@ class Services(DetailHandler):
|
||||
return [
|
||||
{ 'name': {'title': _('Service name'), 'visible': True, 'type': 'iconType' } },
|
||||
{ 'comments': { 'title': _('Comments') } },
|
||||
{ 'type': {'title': _('Type') } }
|
||||
{ 'type': {'title': _('Type') } },
|
||||
{ 'deployed_services_count': {'title': _('Deployed services'), 'type': 'numeric', 'width': '7em'}},
|
||||
]
|
||||
|
||||
def getTypes(self, parent, forType):
|
||||
@ -103,7 +106,12 @@ class Services(DetailHandler):
|
||||
return offers # Default is that details do not have types
|
||||
|
||||
def getGui(self, parent, forType):
|
||||
logger.debug('getGui parameters: {0}, {1}'.format(parent, forType))
|
||||
serviceType = parent.getServiceByType(type)
|
||||
service = serviceType( Environment.getTempEnv(), parent) # Instantiate it so it has the opportunity to alter gui description based on parent
|
||||
return self.addDefaultFields( service.guiDescription(service), ['name', 'comments'])
|
||||
try:
|
||||
logger.debug('getGui parameters: {0}, {1}'.format(parent, forType))
|
||||
parentInstance = parent.getInstance()
|
||||
serviceType = parentInstance.getServiceByType(forType)
|
||||
service = serviceType( Environment.getTempEnv(), parentInstance) # Instantiate it so it has the opportunity to alter gui description based on parent
|
||||
return self.addDefaultFields( service.guiDescription(service), ['name', 'comments'])
|
||||
except Exception as e:
|
||||
logger.exception('getGui')
|
||||
raise ResponseError(unicode(e))
|
||||
|
@ -48,26 +48,24 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class Users(DetailHandler):
|
||||
|
||||
def get(self):
|
||||
def getItems(self, parent, item):
|
||||
# Extract authenticator
|
||||
auth = self._kwargs['parent']
|
||||
|
||||
try:
|
||||
if len(self._args) == 0:
|
||||
return list(auth.users.all().values('id','name','real_name','comments','state','staff_member','is_admin','last_access','parent'))
|
||||
if item is None:
|
||||
return list(parent.users.all().values('id','name','real_name','comments','state','staff_member','is_admin','last_access','parent'))
|
||||
else:
|
||||
return auth.get(pk=self._args[0]).values('id','name','real_name','comments','state','staff_member','is_admin','last_access','parent')
|
||||
return parent.get(pk=item).values('id','name','real_name','comments','state','staff_member','is_admin','last_access','parent')
|
||||
except:
|
||||
logger.exception('En users')
|
||||
return { 'error': 'not found' }
|
||||
|
||||
def getTitle(self):
|
||||
def getTitle(self, parent):
|
||||
try:
|
||||
return _('Users of {0}').format(Authenticator.objects.get(pk=self._kwargs['parent_id']).name)
|
||||
except:
|
||||
return _('Current users')
|
||||
|
||||
def getFields(self):
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'name': {'title': _('User Id'), 'visible': True, 'type': 'icon', 'icon': 'fa fa-user text-success' } },
|
||||
{ 'real_name': { 'title': _('Name') } },
|
||||
@ -77,26 +75,25 @@ class Users(DetailHandler):
|
||||
]
|
||||
|
||||
class Groups(DetailHandler):
|
||||
def get(self):
|
||||
|
||||
def getItems(self, parent, item):
|
||||
# Extract authenticator
|
||||
auth = self._kwargs['parent']
|
||||
|
||||
try:
|
||||
if len(self._args) == 0:
|
||||
return list(auth.groups.all().values('id','name', 'comments','state','is_meta'))
|
||||
if item is None:
|
||||
return list(parent.groups.all().values('id','name', 'comments','state','is_meta'))
|
||||
else:
|
||||
return auth.get(pk=self._args[0]).values('id','name', 'comments','state','is_meta')
|
||||
return parent.get(pk=item).values('id','name', 'comments','state','is_meta')
|
||||
except:
|
||||
logger.exception('REST groups')
|
||||
raise HandlerError('exception')
|
||||
|
||||
def getTitle(self):
|
||||
def getTitle(self, parent):
|
||||
try:
|
||||
return _('Groups of {0}').format(Authenticator.objects.get(pk=self._kwargs['parent_id']).name)
|
||||
except:
|
||||
return _('Current groups')
|
||||
|
||||
def getFields(self):
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'name': {'title': _('User Id'), 'visible': True, 'type': 'icon', 'icon': 'fa fa-group text-success' } },
|
||||
{ 'comments': { 'title': _('Comments') } },
|
||||
|
@ -152,14 +152,13 @@ class DetailHandler(BaseModelHandler):
|
||||
elif self._args[0] == 'tableinfo':
|
||||
return self.processTableFields(self.getTitle(parent), self.getFields(parent))
|
||||
|
||||
raise RequestError('Invalid request')
|
||||
|
||||
#return self.getItems(parent, self._args[0])
|
||||
# try to get id
|
||||
return self.getItems(parent, self._args[0])
|
||||
|
||||
if nArgs == 2:
|
||||
if self._args[1] == 'gui':
|
||||
return self.getGui(parent, self._args[0])
|
||||
elif self._args[1] == 'types':
|
||||
if self._args[0] == 'gui':
|
||||
return self.getGui(parent, self._args[1])
|
||||
elif self._args[0] == 'types':
|
||||
return self.getTypes(parent, self._args[1])
|
||||
|
||||
return self.fallbackGet()
|
||||
@ -268,7 +267,7 @@ class ModelHandler(BaseModelHandler):
|
||||
path = self._path + '/'.join(args[:2])
|
||||
detail = detailCls(self, path, *args, parent = item)
|
||||
return getattr(detail, self._operation)()
|
||||
except:
|
||||
except AttributeError:
|
||||
raise NotFound('method not found')
|
||||
|
||||
def get(self):
|
||||
@ -300,7 +299,7 @@ class ModelHandler(BaseModelHandler):
|
||||
raise NotFound('item not found')
|
||||
|
||||
# nArgs > 1
|
||||
# Request type info
|
||||
# Request type info or gui, or detail
|
||||
if self._args[0] == TYPES:
|
||||
if nArgs != 2:
|
||||
raise RequestError('invalid request')
|
||||
@ -348,6 +347,8 @@ class ModelHandler(BaseModelHandler):
|
||||
item.data_type = self._params['data_type']
|
||||
item.data = item.getInstance(self._params).serialize()
|
||||
|
||||
item.save()
|
||||
|
||||
res = self.item_as_dict(item)
|
||||
|
||||
self.__fillIntanceFields(item, res)
|
||||
|
@ -11,7 +11,6 @@
|
||||
// Equal comparision (like if helper, but with comparation)
|
||||
// Use as block as {{#ifequals [element] [element]}}....{{/ifequals}}
|
||||
Handlebars.registerHelper('ifequals', function(context1, context2, options) {
|
||||
console.log('Comparing ', context1, ' with ', context2);
|
||||
if(context1 == context2) {
|
||||
return options.fn(this);
|
||||
} else {
|
||||
|
@ -350,12 +350,7 @@ BasicModelRest.prototype = {
|
||||
function DetailModelRestApi(parentApi, parentId, model, options) {
|
||||
"use strict";
|
||||
this.options = options;
|
||||
this.base = new BasicModelRest(undefined, {
|
||||
getPath: [parentApi.path, parentId, model].join('/'),
|
||||
typesPath: [parentApi.path, parentId, model, 'types'].join('/'), // Proably this will return nothing
|
||||
guiPath: [parentApi.path, parentId, model].join('/'), // Proably this will return nothing
|
||||
tableInfoPath: [parentApi.path, parentId, model, 'tableinfo'].join('/'),
|
||||
});
|
||||
this.base = new BasicModelRest([parentApi.path, parentId, model].join('/'));
|
||||
}
|
||||
|
||||
DetailModelRestApi.prototype = {
|
||||
@ -378,7 +373,7 @@ DetailModelRestApi.prototype = {
|
||||
},
|
||||
item: function(itemId, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.base.item(success_fnc, fail_fnc);
|
||||
return this.base.item(itemId, success_fnc, fail_fnc);
|
||||
},
|
||||
types: function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
@ -40,23 +40,38 @@ gui.providers.link = function(event) {
|
||||
var tableId = gui.providers.table({
|
||||
container : 'providers-placeholder',
|
||||
rowSelect : 'single',
|
||||
onCheck : function(check, items) { // Check if item can be deleted
|
||||
if( check == 'delete' ) {
|
||||
for( var i in items ) {
|
||||
if( items[i].services_count > 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
onRowSelect : function(selected) {
|
||||
api.tools.blockUI();
|
||||
gui.doLog(selected[0]);
|
||||
var id = selected[0].id;
|
||||
// Options for detail, to initialize types correctly
|
||||
var detail_options = {
|
||||
/* types: function(success_fnc, fail_fnc) {
|
||||
success_fnc(selected[0].offers);
|
||||
}*/
|
||||
};
|
||||
// Giving the name compossed with type, will ensure that only styles will be reattached once
|
||||
var services = new GuiElement(api.providers.detail(id, 'services', detail_options), 'services-'+selected[0].type);
|
||||
var services = new GuiElement(api.providers.detail(id, 'services'), 'services-'+selected[0].type);
|
||||
|
||||
services.table({
|
||||
container : 'services-placeholder',
|
||||
rowSelect : 'single',
|
||||
onCheck: function(check, items) {
|
||||
if( check == 'delete' ) {
|
||||
for( var i in items ) {
|
||||
if( items[i].deployed_services_count > 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
||||
onEdit : services.typedEdit(gettext('Edit service'), gettext('Error processing service')),
|
||||
scrollToTable : false,
|
||||
onLoad: function(k) {
|
||||
api.tools.unblockUI();
|
||||
@ -65,23 +80,7 @@ gui.providers.link = function(event) {
|
||||
return false;
|
||||
},
|
||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
||||
onEdit: function(value, event, table, refreshFnc) {
|
||||
gui.providers.rest.gui(value.type, function(itemGui){
|
||||
gui.providers.rest.item(value.id, function(item) {
|
||||
gui.forms.launchModal(gettext('Edit Service Provider')+' '+value.name, itemGui, item, function(form_selector, closeFnc) {
|
||||
var fields = gui.forms.read(form_selector);
|
||||
fields.data_type = value.type;
|
||||
fields.nets_positive = false;
|
||||
gui.providers.rest.save(fields, function(data) { // Success on put
|
||||
closeFnc();
|
||||
refreshFnc();
|
||||
}, gui.failRequestModalFnc(gettext('Error creating Service Provider')) // Fail on put, show modal message
|
||||
);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
onEdit: gui.providers.typedEdit(gettext('Edit provider'), gettext('Error processing provider')),
|
||||
});
|
||||
});
|
||||
|
||||
@ -136,12 +135,8 @@ gui.authenticators.link = function(event) {
|
||||
onRefresh : function() {
|
||||
$('#users-placeholder').empty(); // Remove detail on parent refresh
|
||||
},
|
||||
onEdit: function(value, event, table) {
|
||||
gui.authenticators.rest.gui(value.type, function(data){
|
||||
var form = gui.fields(data);
|
||||
gui.launchModalForm(gettext('Edit authenticator')+' '+value.name, form);
|
||||
});
|
||||
},
|
||||
onEdit: gui.authenticators.typedEdit(gettext('Edit authenticator'), gettext('Error processing authenticator')),
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -61,6 +61,11 @@ GuiElement.prototype = {
|
||||
// Receives 3 parameters:
|
||||
// 1.- the array of selected items data (objects, as got from api...get)
|
||||
// 2.- the DataTable that raised the event
|
||||
// onCheck: Event (function),
|
||||
// It determines the state of buttons on selection: if returns "true", the indicated button will be enabled, and disabled if returns "false"
|
||||
// Receives 2 parameters:
|
||||
// 1.- the event fired, that can be "edit" or "delete"
|
||||
// 2.- the selected items data (array of selected elements, as got from api...get. In case of edit, array length will be 1)
|
||||
// onNew: Event (function). If defined, will be invoked when "new" button is pressed
|
||||
// Receives 4 parameters:
|
||||
// 1.- the selected item data (single object, as got from api...get)
|
||||
@ -240,10 +245,14 @@ GuiElement.prototype = {
|
||||
};
|
||||
};
|
||||
|
||||
var onCheck = options.onCheck || function() { return true }; // Default oncheck always returns true
|
||||
|
||||
// methods for buttons on row select
|
||||
var editSelected = function(btn, obj, node) {
|
||||
var sel = this.fnGetSelectedData();
|
||||
if (sel.length == 1) {
|
||||
var enable = sel.length == 1 ? onCheck("edit", sel) : false;
|
||||
|
||||
if ( enable) {
|
||||
$(btn).removeClass('disabled').addClass('btn3d-success');
|
||||
} else {
|
||||
$(btn).removeClass('btn3d-success').addClass('disabled');
|
||||
@ -251,7 +260,9 @@ GuiElement.prototype = {
|
||||
};
|
||||
var deleteSelected = function(btn, obj, node) {
|
||||
var sel = this.fnGetSelectedData();
|
||||
if (sel.length > 0) {
|
||||
var enable = sel.length == 1 ? onCheck("delete", sel) : false;
|
||||
|
||||
if (enable) {
|
||||
$(btn).removeClass('disabled').addClass('btn3d-warning');
|
||||
} else {
|
||||
$(btn).removeClass('btn3d-warning').addClass('disabled');
|
||||
@ -434,6 +445,29 @@ GuiElement.prototype = {
|
||||
}); // End Overview data
|
||||
}); // End Tableinfo data
|
||||
return '#' + tableId;
|
||||
}
|
||||
},
|
||||
// "Generic" edit method to set onEdit table
|
||||
typedEdit: function(modalTitle, modalErrorMsg, guiProcessor, fieldsProcessor) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
return function(value, event, table, refreshFnc) {
|
||||
self.rest.gui(value.type, function(guiDefinition) {
|
||||
var tabs = guiProcessor ? guiProcessor(guiDefinition) : guiDefinition;
|
||||
self.rest.item(value.id, function(item) {
|
||||
gui.forms.launchModal(modalTitle+' <b>'+value.name+'</b>', tabs, item, function(form_selector, closeFnc) {
|
||||
var fields = gui.forms.read(form_selector);
|
||||
fields.data_type = value.type;
|
||||
fields = fieldsProcessor ? fieldsProcessor(fields) : fields; // Preprocess fields (probably generate tabs...)
|
||||
self.rest.save(fields, function(data) { // Success on put
|
||||
closeFnc();
|
||||
refreshFnc();
|
||||
}, gui.failRequestModalFnc(modalErrorMsg)); // Fail on put, show modal message
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
}, gui.failRequestModalFnc(modalErrorMsg));
|
||||
};
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -203,6 +203,8 @@
|
||||
max: $.validator.format(gettext("Please enter a value less than or equal to {0}.")),
|
||||
min: $.validator.format(gettext("Please enter a value greater than or equal to {0}."))
|
||||
});
|
||||
// Set blockui params
|
||||
$.blockUI.defaults.baseZ = 2000;
|
||||
|
||||
gui.setLinksEvents();
|
||||
gui.dashboard.link();
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">{{ title }}</h4>
|
||||
<h4 class="modal-title">{{{ title }}}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{{ content }}}
|
||||
|
Loading…
Reference in New Issue
Block a user