forked from shaba/openuds
* Finished (almost) details of master tables
* Added templating engine based on John Resig - http://ejohn.org/, * Added capacity to scroll to make tables visible * Added users detail view for authenticators * added server template serving
This commit is contained in:
parent
d2cf0f6846
commit
6bb538d941
@ -68,6 +68,8 @@ class Types(ModelTypeHandlerMixin, Handler):
|
|||||||
|
|
||||||
class TableInfo(ModelTableHandlerMixin, Handler):
|
class TableInfo(ModelTableHandlerMixin, Handler):
|
||||||
path = 'authenticators'
|
path = 'authenticators'
|
||||||
|
detail = { 'users': Users }
|
||||||
|
|
||||||
title = _('Current authenticators')
|
title = _('Current authenticators')
|
||||||
fields = [
|
fields = [
|
||||||
{ 'name': {'title': _('Name'), 'visible': True } },
|
{ 'name': {'title': _('Name'), 'visible': True } },
|
||||||
|
@ -36,7 +36,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from uds.models import Network
|
from uds.models import Network
|
||||||
|
|
||||||
from uds.REST import Handler, HandlerError
|
from uds.REST import Handler, HandlerError
|
||||||
from uds.REST.mixins import ModelHandlerMixin, ModelTypeHandlerMixin, ModelTableHandlerMixin, ModelFakeType
|
from uds.REST.mixins import ModelHandlerMixin, ModelTypeHandlerMixin, ModelTableHandlerMixin
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -52,7 +52,6 @@ class Networks(ModelHandlerMixin, Handler):
|
|||||||
'name': item.name,
|
'name': item.name,
|
||||||
'net_string': item.net_string,
|
'net_string': item.net_string,
|
||||||
'networks_count': item.transports.count(),
|
'networks_count': item.transports.count(),
|
||||||
'type': 'NetworkType',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Types(ModelTypeHandlerMixin, Handler):
|
class Types(ModelTypeHandlerMixin, Handler):
|
||||||
@ -60,7 +59,7 @@ class Types(ModelTypeHandlerMixin, Handler):
|
|||||||
|
|
||||||
# Fake mathods, to yield self on enum types and get a "fake" type for Network
|
# Fake mathods, to yield self on enum types and get a "fake" type for Network
|
||||||
def enum_types(self):
|
def enum_types(self):
|
||||||
yield ModelFakeType('Network', 'NetworkType', 'A description of a network', '')
|
return []
|
||||||
|
|
||||||
class TableInfo(ModelTableHandlerMixin, Handler):
|
class TableInfo(ModelTableHandlerMixin, Handler):
|
||||||
path = 'networks'
|
path = 'networks'
|
||||||
|
@ -32,10 +32,10 @@
|
|||||||
'''
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
|
|
||||||
from uds.models import User
|
from uds.models import Authenticator, User
|
||||||
|
|
||||||
from uds.REST.mixins import DetailHandler
|
from uds.REST.mixins import DetailHandler
|
||||||
|
|
||||||
@ -78,5 +78,21 @@ class Users(DetailHandler):
|
|||||||
except:
|
except:
|
||||||
logger.exception('En users')
|
logger.exception('En users')
|
||||||
return { 'error': 'not found' }
|
return { 'error': 'not found' }
|
||||||
|
|
||||||
|
def getTitle(self):
|
||||||
|
try:
|
||||||
|
return _('Users of {0}').format(Authenticator.objects.get(pk=self._kwargs['parent_id']))
|
||||||
|
except:
|
||||||
|
return _('Current users')
|
||||||
|
|
||||||
|
def getFields(self):
|
||||||
|
return [
|
||||||
|
{ 'name': {'title': _('User Id'), 'visible': True } },
|
||||||
|
{ 'real_name': { 'title': _('Name') } },
|
||||||
|
{ 'comments': { 'title': _('Comments') } },
|
||||||
|
{ 'state': { 'title': _('state') } },
|
||||||
|
{ 'last_access': { 'title': _('Last access') } },
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -38,12 +38,21 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Details do not have types at all
|
||||||
|
# so, right now, we only process details petitions for Handling & tables info
|
||||||
class DetailHandler(object):
|
class DetailHandler(object):
|
||||||
def __init__(self, parentHandler, path, *args, **kwargs):
|
def __init__(self, parentHandler, path, *args, **kwargs):
|
||||||
self._parent = parentHandler
|
self._parent = parentHandler
|
||||||
self._path = path
|
self._path = path
|
||||||
self._args = args
|
self._args = args
|
||||||
self._kwargs = kwargs
|
self._kwargs = kwargs
|
||||||
|
|
||||||
|
# A detail handler must also return title & fields for tables
|
||||||
|
def getTitle(self):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def getFields(self):
|
||||||
|
return []
|
||||||
|
|
||||||
class ModelHandlerMixin(object):
|
class ModelHandlerMixin(object):
|
||||||
'''
|
'''
|
||||||
@ -61,7 +70,7 @@ class ModelHandlerMixin(object):
|
|||||||
|
|
||||||
def getItems(self, *args, **kwargs):
|
def getItems(self, *args, **kwargs):
|
||||||
for item in self.model.objects.filter(*args, **kwargs):
|
for item in self.model.objects.filter(*args, **kwargs):
|
||||||
try:
|
try:
|
||||||
yield self.item_as_dict(item)
|
yield self.item_as_dict(item)
|
||||||
except:
|
except:
|
||||||
logger.exception('Exception getting item from {0}'.format(self.model))
|
logger.exception('Exception getting item from {0}'.format(self.model))
|
||||||
@ -91,7 +100,8 @@ class ModelHandlerMixin(object):
|
|||||||
item = list(self.getItems(pk=self._args[0]))[0]
|
item = list(self.getItems(pk=self._args[0]))[0]
|
||||||
except:
|
except:
|
||||||
return {'error': 'not found' }
|
return {'error': 'not found' }
|
||||||
|
|
||||||
|
|
||||||
class ModelTypeHandlerMixin(object):
|
class ModelTypeHandlerMixin(object):
|
||||||
'''
|
'''
|
||||||
As With models, a lot of UDS model contains info about its class.
|
As With models, a lot of UDS model contains info about its class.
|
||||||
@ -119,10 +129,12 @@ class ModelTypeHandlerMixin(object):
|
|||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
return list(self.getTypes())
|
return list(self.getTypes())
|
||||||
|
|
||||||
|
|
||||||
class ModelTableHandlerMixin(object):
|
class ModelTableHandlerMixin(object):
|
||||||
authenticated = True
|
authenticated = True
|
||||||
needs_staff = True
|
needs_staff = True
|
||||||
|
detail = None
|
||||||
|
|
||||||
# Fields should have id of the field, type and length
|
# Fields should have id of the field, type and length
|
||||||
# All options can be ommited
|
# All options can be ommited
|
||||||
@ -135,11 +147,29 @@ class ModelTableHandlerMixin(object):
|
|||||||
|
|
||||||
fields = []
|
fields = []
|
||||||
title = ''
|
title = ''
|
||||||
|
|
||||||
|
def processDetail(self):
|
||||||
|
logger.debug('Processing detail for table')
|
||||||
|
try:
|
||||||
|
detailCls = self.detail[self._args[1]]
|
||||||
|
args = list(self._args[2:])
|
||||||
|
path = self._path + '/'.join(args[:2])
|
||||||
|
detail = detailCls(self, path, parent_id = self._args[0])
|
||||||
|
return (detail.getTitle(), detail.getFields())
|
||||||
|
except:
|
||||||
|
return ([], '')
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
# Convert to unicode fields (ugettext_lazy needs to be rendered before passing it to Json
|
if len(self._args) > 1:
|
||||||
fields = [ { 'id' : {'visible': False } } ] # Always add id column as invisible
|
title, fields = self.processDetail()
|
||||||
for f in self.fields:
|
else:
|
||||||
|
# Convert to unicode fields (ugettext_lazy needs to be rendered before passing it to Json
|
||||||
|
title = self.title
|
||||||
|
fields = self.fields # Always add id column as invisible
|
||||||
|
|
||||||
|
processedFields = [{ 'id' : {'visible': False, 'sortable': False, 'searchable': False } }]
|
||||||
|
|
||||||
|
for f in fields:
|
||||||
for k1, v1 in f.iteritems():
|
for k1, v1 in f.iteritems():
|
||||||
dct = {}
|
dct = {}
|
||||||
for k2, v2 in v1.iteritems():
|
for k2, v2 in v1.iteritems():
|
||||||
@ -147,16 +177,6 @@ class ModelTableHandlerMixin(object):
|
|||||||
dct[k2] = v2
|
dct[k2] = v2
|
||||||
else:
|
else:
|
||||||
dct[k2] = unicode(v2)
|
dct[k2] = unicode(v2)
|
||||||
fields.append({k1: dct})
|
processedFields.append({k1: dct})
|
||||||
return { 'title': unicode(self.title), 'fields': fields };
|
return { 'title': unicode(title), 'fields': processedFields };
|
||||||
|
|
||||||
|
|
||||||
# Fake type for models that do not needs typing
|
|
||||||
class ModelFakeType(object):
|
|
||||||
def __init__(self, name, type_, description, icon):
|
|
||||||
self._name, self._type, self._description, self._icon = name, type_, description, icon
|
|
||||||
|
|
||||||
def name(self): return self._name
|
|
||||||
def type(self): return self._type
|
|
||||||
def description(self): return self._description
|
|
||||||
def icon(self): return self._icon
|
|
||||||
|
@ -37,5 +37,6 @@ from uds import REST
|
|||||||
|
|
||||||
urlpatterns = patterns('uds.admin.views',
|
urlpatterns = patterns('uds.admin.views',
|
||||||
(r'^$', 'index'),
|
(r'^$', 'index'),
|
||||||
|
(r'^tmpl/(?P<template>[a-zA-Z0-9]*)$', 'tmpl'),
|
||||||
(r'^sample$', 'sample'),
|
(r'^sample$', 'sample'),
|
||||||
)
|
)
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
|
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
|
||||||
|
from django.template import RequestContext, loader
|
||||||
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
@ -54,6 +56,19 @@ def index(request):
|
|||||||
|
|
||||||
return render(request, 'uds/admin/index.html')
|
return render(request, 'uds/admin/index.html')
|
||||||
|
|
||||||
|
@denyBrowsers(browsers=['ie<9'])
|
||||||
|
@webLoginRequired
|
||||||
|
def tmpl(request, template):
|
||||||
|
if request.user.isStaff() is False:
|
||||||
|
return HttpResponseForbidden(_('Forbidden'))
|
||||||
|
try:
|
||||||
|
t = loader.get_template('uds/admin/tmpl/' + template + ".html")
|
||||||
|
c = RequestContext(request)
|
||||||
|
resp = t.render(c)
|
||||||
|
except:
|
||||||
|
resp = _('requested a template that do not exists')
|
||||||
|
return HttpResponse(resp, content_type="text/plain");
|
||||||
|
|
||||||
@denyBrowsers(browsers=['ie<9'])
|
@denyBrowsers(browsers=['ie<9'])
|
||||||
@webLoginRequired
|
@webLoginRequired
|
||||||
def sample(request):
|
def sample(request):
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
type: "GET",
|
type: "GET",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
api.doLog(gettext('Success on "') + url + '".');
|
api.doLog('Success on "' + url + '".');
|
||||||
api.doLog(gettext('Received ') + JSON.stringify(data));
|
api.doLog('Received ' + JSON.stringify(data));
|
||||||
if( success_fnc != undefined ){
|
if( success_fnc != undefined ){
|
||||||
api.doLog('Executing success method')
|
api.doLog('Executing success method')
|
||||||
success_fnc(data);
|
success_fnc(data);
|
||||||
@ -48,16 +48,16 @@ function BasicModelRest(path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicModelRest.prototype = {
|
BasicModelRest.prototype = {
|
||||||
get: function(options) {
|
get: function(options, alternate_url) {
|
||||||
if( options == undefined ){
|
if( options == undefined ){
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
var path = this.path;
|
var path = alternate_url || this.path;
|
||||||
if( options.id != undefined )
|
if( options.id != undefined )
|
||||||
path += '/' + options.id;
|
path += '/' + options.id;
|
||||||
api.getJson(path, options.success);
|
api.getJson(path, options.success);
|
||||||
},
|
},
|
||||||
types: function(success_fnc) {
|
types: function(success_fnc, alternate_url) {
|
||||||
// Cache types locally, will not change unless new broker version
|
// Cache types locally, will not change unless new broker version
|
||||||
if( this.cached_types ) {
|
if( this.cached_types ) {
|
||||||
if( success_fnc ) {
|
if( success_fnc ) {
|
||||||
@ -66,8 +66,10 @@ BasicModelRest.prototype = {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var $this = this;
|
var $this = this;
|
||||||
|
var path = this.path + '/types';
|
||||||
api.getJson( this.path + '/types', function(data) {
|
if( alternate_url != undefined )
|
||||||
|
path = alternate_url;
|
||||||
|
api.getJson( path, function(data) {
|
||||||
$this.cached_types = data;
|
$this.cached_types = data;
|
||||||
if( success_fnc ) {
|
if( success_fnc ) {
|
||||||
success_fnc($this.cached_types);
|
success_fnc($this.cached_types);
|
||||||
@ -76,7 +78,7 @@ BasicModelRest.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
tableInfo: function(success_fnc) {
|
tableInfo: function(success_fnc, alternate_url) {
|
||||||
// Cache types locally, will not change unless new broker version
|
// Cache types locally, will not change unless new broker version
|
||||||
if( this.cached_tableInfo ) {
|
if( this.cached_tableInfo ) {
|
||||||
if( success_fnc ) {
|
if( success_fnc ) {
|
||||||
@ -85,8 +87,11 @@ BasicModelRest.prototype = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var $this = this;
|
var $this = this;
|
||||||
|
var path = this.path + '/tableinfo';
|
||||||
|
if( alternate_url != undefined )
|
||||||
|
path = alternate_url;
|
||||||
|
|
||||||
api.getJson( this.path + '/tableinfo', function(data) {
|
api.getJson( path, function(data) {
|
||||||
$this.cached_tableInfo = data;
|
$this.cached_tableInfo = data;
|
||||||
if( success_fnc ) {
|
if( success_fnc ) {
|
||||||
success_fnc($this.cached_tableInfo);
|
success_fnc($this.cached_tableInfo);
|
||||||
@ -104,11 +109,24 @@ function DetailModelRestApi(parentApi, path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DetailModelRestApi.prototype = {
|
DetailModelRestApi.prototype = {
|
||||||
|
// Generates a basic model with fixed methods for "detail" models
|
||||||
detail: function(parentId) {
|
detail: function(parentId) {
|
||||||
|
var $this = this;
|
||||||
var rest = new BasicModelRest(this.parentPath + '/' + parentId + '/' + this.path);
|
var rest = new BasicModelRest(this.parentPath + '/' + parentId + '/' + this.path);
|
||||||
|
|
||||||
|
// Overwrite types, detail do not have types
|
||||||
rest.types = function() {
|
rest.types = function() {
|
||||||
return []; // No types at all
|
return []; // No types at all
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// And overwrite tableInfo
|
||||||
|
var parentTableInfo = rest.tableInfo;
|
||||||
|
rest.tableInfo = function(success_fnc, alternate_url) {
|
||||||
|
if( alternate_url == undefined )
|
||||||
|
alternate_url = $this.parentPath + '/tableinfo/' + parentId + '/' + $this.path;
|
||||||
|
parentTableInfo( success_fnc, alternate_url )
|
||||||
|
}
|
||||||
|
return rest;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,4 +140,66 @@ api.authenticators.users = new DetailModelRestApi(api.authenticators, 'users');
|
|||||||
|
|
||||||
api.osmanagers = new BasicModelRest('osmanagers');
|
api.osmanagers = new BasicModelRest('osmanagers');
|
||||||
api.transports = new BasicModelRest('transports');
|
api.transports = new BasicModelRest('transports');
|
||||||
api.networks = new BasicModelRest('networks');
|
api.networks = new BasicModelRest('networks');
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------
|
||||||
|
// Templates related
|
||||||
|
// This is not part of REST api provided by UDS, but it's part of the api needed for the admin app
|
||||||
|
// -------------------------------
|
||||||
|
(function(templates, $){
|
||||||
|
templates.cache = {}; // Will cache templates locally. If name contains '?', data will not be cached and always re-requested
|
||||||
|
templates.get = function(name, success_fnc) {
|
||||||
|
if( !name.contains('?') ) {
|
||||||
|
if( templates.cache[name] != undefined ) {
|
||||||
|
if( success_fnc != undefined ) {
|
||||||
|
success_fnc(templates.cache[name]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
url: '/adm/tmpl/' + name,
|
||||||
|
type: "GET",
|
||||||
|
dataType: "text",
|
||||||
|
success: function(data) {
|
||||||
|
templates.cache[name] = data;
|
||||||
|
api.doLog('Success getting template "' + name + '".');
|
||||||
|
api.doLog('Received: ' + data);
|
||||||
|
if( success_fnc != undefined ){
|
||||||
|
api.doLog('Executing success method')
|
||||||
|
success_fnc(data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Simple JavaScript Templating
|
||||||
|
// Based on John Resig - http://ejohn.org/ - MIT Licensed
|
||||||
|
templates.eval = function tmpl(str, data){
|
||||||
|
// Figure out if we're getting a template, or if we need to
|
||||||
|
// load the template - and be sure to cache the result.
|
||||||
|
var fn =
|
||||||
|
// Generate a reusable function that will serve as a template
|
||||||
|
// generator (and which will be cached).
|
||||||
|
new Function("obj",
|
||||||
|
"var p=[],print=function(){p.push.apply(p,arguments);};" +
|
||||||
|
|
||||||
|
// Introduce the data as local variables using with(){}
|
||||||
|
"with(obj){p.push('" +
|
||||||
|
|
||||||
|
// Convert the template into pure JavaScript
|
||||||
|
str
|
||||||
|
.replace(/[\r\t\n]/g, " ")
|
||||||
|
.split("<%").join("\t")
|
||||||
|
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
|
||||||
|
.replace(/\t=(.*?)%>/g, "',$1,'")
|
||||||
|
.split("\t").join("');")
|
||||||
|
.split("%>").join("p.push('")
|
||||||
|
.split("\r").join("\\'")
|
||||||
|
+ "');}return p.join('');");
|
||||||
|
|
||||||
|
// Provide some basic currying to the user
|
||||||
|
return data ? fn( data ) : fn;
|
||||||
|
};
|
||||||
|
}(api.templates = api.templates || {}, jQuery));
|
||||||
|
87
server/src/uds/static/adm/js/gui-elements.js
Normal file
87
server/src/uds/static/adm/js/gui-elements.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Compose gui elements
|
||||||
|
|
||||||
|
// Service providers
|
||||||
|
gui.providers = new GuiElement(api.providers, 'provi');
|
||||||
|
gui.providers.link = function(event) {
|
||||||
|
gui.clearWorkspace();
|
||||||
|
gui.appendToWorkspace(gui.breadcrumbs(gettext('Service Providers')));
|
||||||
|
|
||||||
|
var tableId = gui.providers.table({
|
||||||
|
rowSelect: 'multi',
|
||||||
|
rowSelectFnc: function(nodes){
|
||||||
|
gui.doLog(nodes);
|
||||||
|
gui.doLog(this);
|
||||||
|
gui.doLog(this.fnGetSelectedData());
|
||||||
|
},
|
||||||
|
buttons: ['edit', 'refresh', 'delete'],
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------..
|
||||||
|
// Authenticators
|
||||||
|
// ---------------
|
||||||
|
gui.authenticators = new GuiElement(api.authenticators, 'auth');
|
||||||
|
|
||||||
|
gui.authenticators.link = function(event) {
|
||||||
|
api.templates.get('authenticators', function(tmpl){
|
||||||
|
gui.clearWorkspace();
|
||||||
|
gui.appendToWorkspace(api.templates.eval(tmpl, { auths: 'auths-placeholder', users: 'users-placeholder' }));
|
||||||
|
gui.setLinksEvents();
|
||||||
|
|
||||||
|
gui.authenticators.table({
|
||||||
|
container: 'auths-placeholder',
|
||||||
|
rowSelect: 'single',
|
||||||
|
buttons: ['edit', 'refresh', 'delete'],
|
||||||
|
rowSelectFnc: function(nodes){
|
||||||
|
var id = this.fnGetSelectedData()[0].id;
|
||||||
|
var user = new GuiElement(api.authenticators.users.detail(id), 'users');
|
||||||
|
user.table({
|
||||||
|
container: 'users-placeholder',
|
||||||
|
rowSelect: 'multi',
|
||||||
|
buttons: ['edit', 'refresh', 'delete'],
|
||||||
|
scroll: true,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
gui.osmanagers = new GuiElement(api.osmanagers, 'osm');
|
||||||
|
gui.osmanagers.link = function(event) {
|
||||||
|
gui.clearWorkspace();
|
||||||
|
gui.appendToWorkspace(gui.breadcrumbs('Os Managers'));
|
||||||
|
|
||||||
|
gui.osmanagers.table({
|
||||||
|
rowSelect: 'single',
|
||||||
|
buttons: ['edit', 'refresh', 'delete'],
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
gui.connectivity = {
|
||||||
|
transports: new GuiElement(api.transports, 'trans'),
|
||||||
|
networks: new GuiElement(api.networks, 'nets'),
|
||||||
|
};
|
||||||
|
|
||||||
|
gui.connectivity.link = function(event) {
|
||||||
|
gui.clearWorkspace();
|
||||||
|
gui.appendToWorkspace(gui.breadcrumbs(gettext('Connectivity')));
|
||||||
|
gui.appendToWorkspace('<div class="row"><div class="col-lg-6" id="ttbl"></div><div class="col-lg-6" id="ntbl"></div></div>');
|
||||||
|
|
||||||
|
gui.connectivity.transports.table({
|
||||||
|
rowSelect: 'multi',
|
||||||
|
container: 'ttbl',
|
||||||
|
buttons: ['edit', 'refresh', 'delete', 'pdf'],
|
||||||
|
});
|
||||||
|
gui.connectivity.networks.table({
|
||||||
|
rowSelect: 'single',
|
||||||
|
container: 'ntbl',
|
||||||
|
buttons: ['edit', 'refresh', 'delete'],
|
||||||
|
});
|
||||||
|
}
|
@ -15,7 +15,7 @@
|
|||||||
// Several convenience "constants"
|
// Several convenience "constants"
|
||||||
gui.dataTablesLanguage = {
|
gui.dataTablesLanguage = {
|
||||||
"sLengthMenu": gettext("_MENU_ records per page"),
|
"sLengthMenu": gettext("_MENU_ records per page"),
|
||||||
"sZeroRecords": gettext("Nothing found - sorry"),
|
"sZeroRecords": gettext("Empty"),
|
||||||
"sInfo": gettext("Records _START_ to _END_ of _TOTAL_"),
|
"sInfo": gettext("Records _START_ to _END_ of _TOTAL_"),
|
||||||
"sInfoEmpty": gettext("No records"),
|
"sInfoEmpty": gettext("No records"),
|
||||||
"sInfoFiltered": gettext("(filtered from _MAX_ total records)"),
|
"sInfoFiltered": gettext("(filtered from _MAX_ total records)"),
|
||||||
@ -88,13 +88,13 @@
|
|||||||
];
|
];
|
||||||
$.each(sidebarLinks, function(index, value){
|
$.each(sidebarLinks, function(index, value){
|
||||||
gui.doLog('Adding ' + value.id)
|
gui.doLog('Adding ' + value.id)
|
||||||
$('.'+value.id).unbind('click').click(value.exec);
|
$('.'+value.id).unbind('click').click(function(event) {
|
||||||
// Navbar click so navbar is closed...
|
if($('.navbar-toggle').css('display') !='none') {
|
||||||
$('.nav a').on('click', function(){
|
|
||||||
if($('.navbar-toggle').css('display') !='none'){
|
|
||||||
$(".navbar-toggle").trigger( "click" );
|
$(".navbar-toggle").trigger( "click" );
|
||||||
}
|
}
|
||||||
});
|
$('html, body').scrollTop(0);
|
||||||
|
value.exec(event);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +162,8 @@ GuiElement.prototype = {
|
|||||||
column.bVisible = options.visible;
|
column.bVisible = options.visible;
|
||||||
if( options.sortable != undefined )
|
if( options.sortable != undefined )
|
||||||
column.bSortable = options.sortable;
|
column.bSortable = options.sortable;
|
||||||
|
if( options.searchable != undefined )
|
||||||
|
column.bSearchable = options.searchable;
|
||||||
|
|
||||||
// Fix name columm so we can add a class icon
|
// Fix name columm so we can add a class icon
|
||||||
if( v == 'name' ) {
|
if( v == 'name' ) {
|
||||||
@ -174,10 +176,17 @@ GuiElement.prototype = {
|
|||||||
gui.doLog(columns);
|
gui.doLog(columns);
|
||||||
|
|
||||||
var processResponse = function(data) {
|
var processResponse = function(data) {
|
||||||
$.each(data, function(index, value){
|
// If it has a "type" column
|
||||||
var type = $this.types[value.type];
|
try {
|
||||||
data[index].name = '<span class="' + type.css + '"> </span> ' + value.name
|
if( data[0].type != undefined ) {
|
||||||
});
|
$.each(data, function(index, value){
|
||||||
|
var type = $this.types[value.type];
|
||||||
|
data[index].name = '<span class="' + type.css + '"> </span> ' + value.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$this.rest.get({
|
$this.rest.get({
|
||||||
@ -319,6 +328,11 @@ GuiElement.prototype = {
|
|||||||
|
|
||||||
});
|
});
|
||||||
$('#' + tableId + '_filter input').addClass('form-control');
|
$('#' + tableId + '_filter input').addClass('form-control');
|
||||||
|
var tableTop = $('#'+tableId).offset().top;
|
||||||
|
gui.doLog(tableTop);
|
||||||
|
//$('html, body').animate({ scrollTop: tableTop });
|
||||||
|
if( options.scroll )
|
||||||
|
$('html, body').scrollTop(tableTop);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -326,73 +340,3 @@ GuiElement.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compose gui API
|
|
||||||
|
|
||||||
// Service providers
|
|
||||||
gui.providers = new GuiElement(api.providers, 'provi');
|
|
||||||
gui.providers.link = function(event) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Service Providers')));
|
|
||||||
|
|
||||||
var tableId = gui.providers.table({
|
|
||||||
rowSelect: 'multi',
|
|
||||||
rowSelectFnc: function(nodes){
|
|
||||||
gui.doLog(nodes);
|
|
||||||
gui.doLog(this);
|
|
||||||
gui.doLog(this.fnGetSelectedData());
|
|
||||||
},
|
|
||||||
buttons: ['edit', 'refresh', 'delete'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.authenticators = new GuiElement(api.authenticators, 'auth');
|
|
||||||
|
|
||||||
gui.authenticators.link = function(event) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Authenticators')));
|
|
||||||
|
|
||||||
gui.authenticators.table({
|
|
||||||
rowSelect: 'single',
|
|
||||||
buttons: ['edit', 'refresh', 'delete'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.osmanagers = new GuiElement(api.osmanagers, 'osm');
|
|
||||||
gui.osmanagers.link = function(event) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(gui.breadcrumbs('Os Managers'));
|
|
||||||
|
|
||||||
gui.osmanagers.table({
|
|
||||||
rowSelect: 'single',
|
|
||||||
buttons: ['edit', 'refresh', 'delete'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.connectivity = {
|
|
||||||
transports: new GuiElement(api.transports, 'trans'),
|
|
||||||
networks: new GuiElement(api.networks, 'nets'),
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.connectivity.link = function(event) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Connectivity')));
|
|
||||||
gui.appendToWorkspace('<div class="row"><div class="col-lg-6" id="ttbl"></div><div class="col-lg-6" id="ntbl"></div></div>');
|
|
||||||
|
|
||||||
gui.connectivity.transports.table({
|
|
||||||
rowSelect: 'multi',
|
|
||||||
container: 'ttbl',
|
|
||||||
buttons: ['edit', 'refresh', 'delete', 'pdf'],
|
|
||||||
});
|
|
||||||
gui.connectivity.networks.table({
|
|
||||||
rowSelect: 'single',
|
|
||||||
container: 'ntbl',
|
|
||||||
buttons: ['edit', 'refresh', 'delete'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,35 +1 @@
|
|||||||
// Simple JavaScript Templating
|
|
||||||
// John Resig - http://ejohn.org/ - MIT Licensed
|
|
||||||
(function(){
|
|
||||||
var cache = {};
|
|
||||||
|
|
||||||
this.tmpl = function tmpl(str, data){
|
|
||||||
// Figure out if we're getting a template, or if we need to
|
|
||||||
// load the template - and be sure to cache the result.
|
|
||||||
var fn = !/\W/.test(str) ?
|
|
||||||
cache[str] = cache[str] ||
|
|
||||||
tmpl(document.getElementById(str).innerHTML) :
|
|
||||||
|
|
||||||
// Generate a reusable function that will serve as a template
|
|
||||||
// generator (and which will be cached).
|
|
||||||
new Function("obj",
|
|
||||||
"var p=[],print=function(){p.push.apply(p,arguments);};" +
|
|
||||||
|
|
||||||
// Introduce the data as local variables using with(){}
|
|
||||||
"with(obj){p.push('" +
|
|
||||||
|
|
||||||
// Convert the template into pure JavaScript
|
|
||||||
str
|
|
||||||
.replace(/[\r\t\n]/g, " ")
|
|
||||||
.split("<$").join("\t")
|
|
||||||
.replace(/((^|$>)[^\t]*)'/g, "$1\r")
|
|
||||||
.replace(/\t=(.*?)$>/g, "',$1,'")
|
|
||||||
.split("\t").join("');")
|
|
||||||
.split("$>").join("p.push('")
|
|
||||||
.split("\r").join("\\'")
|
|
||||||
+ "');}return p.join('');");
|
|
||||||
|
|
||||||
// Provide some basic currying to the user
|
|
||||||
return data ? fn( data ) : fn;
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<script src="{% get_static_prefix %}adm/js/api.js"></script>
|
<script src="{% get_static_prefix %}adm/js/api.js"></script>
|
||||||
<script src="{% get_static_prefix %}adm/js/gui.js"></script>
|
<script src="{% get_static_prefix %}adm/js/gui.js"></script>
|
||||||
|
<script src="{% get_static_prefix %}adm/js/gui-elements.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
|
18
server/src/uds/templates/uds/admin/tmpl/authenticators.html
Normal file
18
server/src/uds/templates/uds/admin/tmpl/authenticators.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{% load i18n html5 static %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<h1>{% trans 'Authenticators' %} <small>{% trans 'administration of authenticators' %}</small></h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a class="lnk-dashboard" href="#"><i class="fa fa-dashboard"></i> Dashboard</a></li>
|
||||||
|
<li>otra cosa</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div><!-- /.row -->
|
||||||
|
<div class="row">
|
||||||
|
<div id="<%= auths %>" class="col-xs-12">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div id="<%= users %>" class="col-xs-12">
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -62,7 +62,7 @@ urlpatterns = patterns('uds',
|
|||||||
# Change Language
|
# Change Language
|
||||||
(r'^i18n/', include('django.conf.urls.i18n')),
|
(r'^i18n/', include('django.conf.urls.i18n')),
|
||||||
# Downloadables
|
# Downloadables
|
||||||
(r'^download/(?P<idDownload>.*)$', 'web.views.download'),
|
(r'^download/(?P<idDownload>[a-zA-Z0-9]*)$', 'web.views.download'),
|
||||||
# Custom authentication callback
|
# Custom authentication callback
|
||||||
(r'^auth/(?P<authName>.+)', 'web.views.authCallback'),
|
(r'^auth/(?P<authName>.+)', 'web.views.authCallback'),
|
||||||
(r'^authJava/(?P<idAuth>.+)/(?P<hasJava>.*)$', 'web.views.authJava'),
|
(r'^authJava/(?P<idAuth>.+)/(?P<hasJava>.*)$', 'web.views.authJava'),
|
||||||
|
Loading…
Reference in New Issue
Block a user