mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
* 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):
|
||||
path = 'authenticators'
|
||||
detail = { 'users': Users }
|
||||
|
||||
title = _('Current authenticators')
|
||||
fields = [
|
||||
{ 'name': {'title': _('Name'), 'visible': True } },
|
||||
|
@ -36,7 +36,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from uds.models import Network
|
||||
|
||||
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
|
||||
|
||||
@ -52,7 +52,6 @@ class Networks(ModelHandlerMixin, Handler):
|
||||
'name': item.name,
|
||||
'net_string': item.net_string,
|
||||
'networks_count': item.transports.count(),
|
||||
'type': 'NetworkType',
|
||||
}
|
||||
|
||||
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
|
||||
def enum_types(self):
|
||||
yield ModelFakeType('Network', 'NetworkType', 'A description of a network', '')
|
||||
return []
|
||||
|
||||
class TableInfo(ModelTableHandlerMixin, Handler):
|
||||
path = 'networks'
|
||||
|
@ -32,10 +32,10 @@
|
||||
'''
|
||||
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 uds.models import User
|
||||
from uds.models import Authenticator, User
|
||||
|
||||
from uds.REST.mixins import DetailHandler
|
||||
|
||||
@ -78,5 +78,21 @@ class Users(DetailHandler):
|
||||
except:
|
||||
logger.exception('En users')
|
||||
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__)
|
||||
|
||||
# Details do not have types at all
|
||||
# so, right now, we only process details petitions for Handling & tables info
|
||||
class DetailHandler(object):
|
||||
def __init__(self, parentHandler, path, *args, **kwargs):
|
||||
self._parent = parentHandler
|
||||
self._path = path
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
|
||||
# A detail handler must also return title & fields for tables
|
||||
def getTitle(self):
|
||||
return ''
|
||||
|
||||
def getFields(self):
|
||||
return []
|
||||
|
||||
class ModelHandlerMixin(object):
|
||||
'''
|
||||
@ -61,7 +70,7 @@ class ModelHandlerMixin(object):
|
||||
|
||||
def getItems(self, *args, **kwargs):
|
||||
for item in self.model.objects.filter(*args, **kwargs):
|
||||
try:
|
||||
try:
|
||||
yield self.item_as_dict(item)
|
||||
except:
|
||||
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]
|
||||
except:
|
||||
return {'error': 'not found' }
|
||||
|
||||
|
||||
|
||||
class ModelTypeHandlerMixin(object):
|
||||
'''
|
||||
As With models, a lot of UDS model contains info about its class.
|
||||
@ -119,10 +129,12 @@ class ModelTypeHandlerMixin(object):
|
||||
|
||||
def get(self):
|
||||
return list(self.getTypes())
|
||||
|
||||
|
||||
class ModelTableHandlerMixin(object):
|
||||
authenticated = True
|
||||
needs_staff = True
|
||||
detail = None
|
||||
|
||||
# Fields should have id of the field, type and length
|
||||
# All options can be ommited
|
||||
@ -135,11 +147,29 @@ class ModelTableHandlerMixin(object):
|
||||
|
||||
fields = []
|
||||
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):
|
||||
# Convert to unicode fields (ugettext_lazy needs to be rendered before passing it to Json
|
||||
fields = [ { 'id' : {'visible': False } } ] # Always add id column as invisible
|
||||
for f in self.fields:
|
||||
if len(self._args) > 1:
|
||||
title, fields = self.processDetail()
|
||||
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():
|
||||
dct = {}
|
||||
for k2, v2 in v1.iteritems():
|
||||
@ -147,16 +177,6 @@ class ModelTableHandlerMixin(object):
|
||||
dct[k2] = v2
|
||||
else:
|
||||
dct[k2] = unicode(v2)
|
||||
fields.append({k1: dct})
|
||||
return { 'title': unicode(self.title), 'fields': fields };
|
||||
processedFields.append({k1: dct})
|
||||
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',
|
||||
(r'^$', 'index'),
|
||||
(r'^tmpl/(?P<template>[a-zA-Z0-9]*)$', 'tmpl'),
|
||||
(r'^sample$', 'sample'),
|
||||
)
|
||||
|
@ -31,6 +31,8 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.template import RequestContext, loader
|
||||
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import ugettext as _
|
||||
@ -54,6 +56,19 @@ def index(request):
|
||||
|
||||
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'])
|
||||
@webLoginRequired
|
||||
def sample(request):
|
||||
|
@ -20,8 +20,8 @@
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
api.doLog(gettext('Success on "') + url + '".');
|
||||
api.doLog(gettext('Received ') + JSON.stringify(data));
|
||||
api.doLog('Success on "' + url + '".');
|
||||
api.doLog('Received ' + JSON.stringify(data));
|
||||
if( success_fnc != undefined ){
|
||||
api.doLog('Executing success method')
|
||||
success_fnc(data);
|
||||
@ -48,16 +48,16 @@ function BasicModelRest(path) {
|
||||
}
|
||||
|
||||
BasicModelRest.prototype = {
|
||||
get: function(options) {
|
||||
get: function(options, alternate_url) {
|
||||
if( options == undefined ){
|
||||
options = {};
|
||||
}
|
||||
var path = this.path;
|
||||
var path = alternate_url || this.path;
|
||||
if( options.id != undefined )
|
||||
path += '/' + options.id;
|
||||
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
|
||||
if( this.cached_types ) {
|
||||
if( success_fnc ) {
|
||||
@ -66,8 +66,10 @@ BasicModelRest.prototype = {
|
||||
}
|
||||
else {
|
||||
var $this = this;
|
||||
|
||||
api.getJson( this.path + '/types', function(data) {
|
||||
var path = this.path + '/types';
|
||||
if( alternate_url != undefined )
|
||||
path = alternate_url;
|
||||
api.getJson( path, function(data) {
|
||||
$this.cached_types = data;
|
||||
if( success_fnc ) {
|
||||
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
|
||||
if( this.cached_tableInfo ) {
|
||||
if( success_fnc ) {
|
||||
@ -85,8 +87,11 @@ BasicModelRest.prototype = {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
if( success_fnc ) {
|
||||
success_fnc($this.cached_tableInfo);
|
||||
@ -104,11 +109,24 @@ function DetailModelRestApi(parentApi, path) {
|
||||
}
|
||||
|
||||
DetailModelRestApi.prototype = {
|
||||
// Generates a basic model with fixed methods for "detail" models
|
||||
detail: function(parentId) {
|
||||
var $this = this;
|
||||
var rest = new BasicModelRest(this.parentPath + '/' + parentId + '/' + this.path);
|
||||
|
||||
// Overwrite types, detail do not have types
|
||||
rest.types = function() {
|
||||
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.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"
|
||||
gui.dataTablesLanguage = {
|
||||
"sLengthMenu": gettext("_MENU_ records per page"),
|
||||
"sZeroRecords": gettext("Nothing found - sorry"),
|
||||
"sZeroRecords": gettext("Empty"),
|
||||
"sInfo": gettext("Records _START_ to _END_ of _TOTAL_"),
|
||||
"sInfoEmpty": gettext("No records"),
|
||||
"sInfoFiltered": gettext("(filtered from _MAX_ total records)"),
|
||||
@ -88,13 +88,13 @@
|
||||
];
|
||||
$.each(sidebarLinks, function(index, value){
|
||||
gui.doLog('Adding ' + value.id)
|
||||
$('.'+value.id).unbind('click').click(value.exec);
|
||||
// Navbar click so navbar is closed...
|
||||
$('.nav a').on('click', function(){
|
||||
if($('.navbar-toggle').css('display') !='none'){
|
||||
$('.'+value.id).unbind('click').click(function(event) {
|
||||
if($('.navbar-toggle').css('display') !='none') {
|
||||
$(".navbar-toggle").trigger( "click" );
|
||||
}
|
||||
});
|
||||
$('html, body').scrollTop(0);
|
||||
value.exec(event);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -162,6 +162,8 @@ GuiElement.prototype = {
|
||||
column.bVisible = options.visible;
|
||||
if( options.sortable != undefined )
|
||||
column.bSortable = options.sortable;
|
||||
if( options.searchable != undefined )
|
||||
column.bSearchable = options.searchable;
|
||||
|
||||
// Fix name columm so we can add a class icon
|
||||
if( v == 'name' ) {
|
||||
@ -174,10 +176,17 @@ GuiElement.prototype = {
|
||||
gui.doLog(columns);
|
||||
|
||||
var processResponse = function(data) {
|
||||
$.each(data, function(index, value){
|
||||
var type = $this.types[value.type];
|
||||
data[index].name = '<span class="' + type.css + '"> </span> ' + value.name
|
||||
});
|
||||
// If it has a "type" column
|
||||
try {
|
||||
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({
|
||||
@ -319,6 +328,11 @@ GuiElement.prototype = {
|
||||
|
||||
});
|
||||
$('#' + 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 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-elements.js"></script>
|
||||
|
||||
<script>
|
||||
$(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
|
||||
(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
# Downloadables
|
||||
(r'^download/(?P<idDownload>.*)$', 'web.views.download'),
|
||||
(r'^download/(?P<idDownload>[a-zA-Z0-9]*)$', 'web.views.download'),
|
||||
# Custom authentication callback
|
||||
(r'^auth/(?P<authName>.+)', 'web.views.authCallback'),
|
||||
(r'^authJava/(?P<idAuth>.+)/(?P<hasJava>.*)$', 'web.views.authJava'),
|
||||
|
Loading…
Reference in New Issue
Block a user