forked from shaba/openuds
Adding the posibility to include custom buttons on modal footers, so we can for example add "test" buttons wherever they are needed
This commit is contained in:
parent
f5e5d88973
commit
c29e2d4dcb
@ -38,7 +38,7 @@ from uds.core import auths
|
||||
|
||||
|
||||
from users_groups import Users, Groups
|
||||
from uds.REST import Handler, NotFound
|
||||
from uds.REST import NotFound
|
||||
from uds.REST.model import ModelHandler
|
||||
|
||||
import logging
|
||||
@ -50,12 +50,14 @@ logger = logging.getLogger(__name__)
|
||||
class Authenticators(ModelHandler):
|
||||
model = Authenticator
|
||||
detail = { 'users': Users, 'groups':Groups }
|
||||
save_fields = ['name', 'comments']
|
||||
save_fields = ['name', 'comments', 'priority', 'small_name']
|
||||
|
||||
table_title = _('Current authenticators')
|
||||
table_fields = [
|
||||
{ 'name': {'title': _('Name'), 'visible': True, 'type': 'iconType' } },
|
||||
{ 'comments': {'title': _('Comments')}},
|
||||
{ 'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '5em'}},
|
||||
{ 'small_name': {'title': _('Small name')}},
|
||||
{ 'users_count': {'title': _('Users'), 'type': 'numeric', 'width': '5em'}}
|
||||
]
|
||||
|
||||
@ -64,7 +66,7 @@ class Authenticators(ModelHandler):
|
||||
|
||||
def getGui(self, type_):
|
||||
try:
|
||||
return self.addDefaultFields(auths.factory().lookup(type_).guiDescription(), ['name', 'comments'])
|
||||
return self.addDefaultFields(auths.factory().lookup(type_).guiDescription(), ['name', 'comments', 'priority', 'small_name'])
|
||||
except:
|
||||
raise NotFound('type not found')
|
||||
|
||||
@ -72,8 +74,10 @@ class Authenticators(ModelHandler):
|
||||
type_ = auth.getType()
|
||||
return { 'id': auth.id,
|
||||
'name': auth.name,
|
||||
'comments': auth.comments,
|
||||
'priority': auth.priority,
|
||||
'small_name': auth.small_name,
|
||||
'users_count': auth.users.count(),
|
||||
'type': type_.type(),
|
||||
'comments': auth.comments,
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,6 @@ class BaseModelHandler(Handler):
|
||||
'tooltip': _('Name of this element'),
|
||||
'order': -100,
|
||||
})
|
||||
# And maybe comments (only if model has this field)
|
||||
if 'comments' in flds:
|
||||
self.addField(gui, {
|
||||
'name': 'comments',
|
||||
@ -88,6 +87,25 @@ class BaseModelHandler(Handler):
|
||||
'length': 256,
|
||||
'order': -99,
|
||||
})
|
||||
if 'priority' in flds:
|
||||
self.addField(gui, {
|
||||
'name': 'priority',
|
||||
'type': 'numeric',
|
||||
'label': _('Priority'),
|
||||
'tooltip': _('Selects the priority of this element (lower number means higher priority)'),
|
||||
'length': 4,
|
||||
'order': -98,
|
||||
})
|
||||
if 'small_name' in flds:
|
||||
self.addField(gui, {
|
||||
'name': 'small_name',
|
||||
'type': 'text',
|
||||
'label': _('Small name'),
|
||||
'tooltip': _('Small name of this element'),
|
||||
'length': 128,
|
||||
'order': -97,
|
||||
})
|
||||
|
||||
return gui
|
||||
|
||||
def type_as_dict(self, type_):
|
||||
|
@ -48,7 +48,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@denyBrowsers(browsers=['ie<9'])
|
||||
@denyBrowsers(browsers=['ie<10'])
|
||||
@webLoginRequired
|
||||
def index(request):
|
||||
if request.user.isStaff() is False:
|
||||
|
@ -29,10 +29,6 @@ gui.dashboard.link = function(event) {
|
||||
gui.providers = new GuiElement(api.providers, 'provi');
|
||||
gui.providers.link = function(event) {
|
||||
"use strict";
|
||||
// Cleans up memory used by other datatables
|
||||
$.each($.fn.dataTable.fnTables(), function(undefined, tbl){
|
||||
$(tbl).dataTable().fnDestroy();
|
||||
});
|
||||
|
||||
api.templates.get('providers', function(tmpl) {
|
||||
gui.clearWorkspace();
|
||||
@ -117,6 +113,20 @@ gui.authenticators.link = function(event) {
|
||||
}));
|
||||
gui.setLinksEvents();
|
||||
|
||||
|
||||
// Button definition to trigger "Test" action
|
||||
var testButton = {
|
||||
buttons: [
|
||||
{
|
||||
text: gettext('Test authenticator'),
|
||||
css: 'btn-info',
|
||||
action: function(event, form_selector, closeFnc) {
|
||||
var fields = gui.forms.read(form_selector);
|
||||
}
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
gui.authenticators.table({
|
||||
container : 'auths-placeholder',
|
||||
rowSelect : 'single',
|
||||
@ -148,8 +158,8 @@ gui.authenticators.link = function(event) {
|
||||
onRefresh : function() {
|
||||
$('#users-placeholder').empty(); // Remove detail on parent refresh
|
||||
},
|
||||
onNew : gui.methods.typedNew(gui.authenticators, gettext('New authenticator'), gettext('Error creating authenticator')),
|
||||
onEdit: gui.methods.typedEdit(gui.authenticators, gettext('Edit authenticator'), gettext('Error processing authenticator')),
|
||||
onNew : gui.methods.typedNew(gui.authenticators, gettext('New authenticator'), gettext('Error creating authenticator'),testButton),
|
||||
onEdit: gui.methods.typedEdit(gui.authenticators, gettext('Edit authenticator'), gettext('Error processing authenticator'), testButton),
|
||||
onDelete: gui.methods.del(gui.authenticators, gettext('Delete authenticator'), gettext('Error deleting authenticator')),
|
||||
|
||||
});
|
||||
@ -282,7 +292,7 @@ gui.clear_cache.link = function() {
|
||||
"use strict";
|
||||
api.getJson('cache/flush', {
|
||||
success: function() {
|
||||
gui.launchModal(gettext('Cache'), gettext('Cache has been flushed'), ' ' );
|
||||
gui.launchModal(gettext('Cache'), gettext('Cache has been flushed'), { actionButton: ' ' } );
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -44,6 +44,7 @@ GuiElement.prototype = {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Options: dictionary
|
||||
// container: container ID of parent for the table. If undefined, table will be appended to workspace
|
||||
// buttons: array of visible buttons (strings), valid are [ 'new', 'edit', 'refresh', 'delete', 'xls' ],
|
||||
@ -212,7 +213,7 @@ GuiElement.prototype = {
|
||||
var tbl = $('#' + tableId).dataTable();
|
||||
// Clears selection first
|
||||
TableTools.fnGetInstance(tableId).fnSelectNone();
|
||||
if( data.length > 1000 )
|
||||
//if( data.length > 1000 )
|
||||
api.tools.blockUI();
|
||||
|
||||
self.rest.overview(function(data) { // Restore overview
|
||||
@ -245,7 +246,7 @@ GuiElement.prototype = {
|
||||
};
|
||||
};
|
||||
|
||||
var onCheck = options.onCheck || function() { return true }; // Default oncheck always returns true
|
||||
var onCheck = options.onCheck || function(){ return true; }; // Default oncheck always returns true
|
||||
|
||||
// methods for buttons on row select
|
||||
var editSelected = function(btn, obj, node) {
|
||||
@ -445,7 +446,6 @@ GuiElement.prototype = {
|
||||
}); // End Overview data
|
||||
}); // End Tableinfo data
|
||||
|
||||
$('.DTTT_dropdown').remove(); // Tabletools keep adding garbage to end of body on each new table creation, so we simply remove it on each new creation
|
||||
return '#' + tableId;
|
||||
},
|
||||
};
|
||||
|
@ -105,14 +105,6 @@
|
||||
var init = function(formSelector) {
|
||||
gui.doLog(formSelector, fillers);
|
||||
|
||||
/*var pos = 0;
|
||||
var triggerChangeSequentially = function() {
|
||||
if( pos >= fillers.length )
|
||||
return;
|
||||
$(formSelector + ' [name="' + fillers[pos].name + '"]').trigger('change');
|
||||
pos = pos + 1;
|
||||
};*/
|
||||
|
||||
var onChange = function(filler) {
|
||||
return function() {
|
||||
gui.doLog('Onchange invoked for ', filler);
|
||||
@ -132,14 +124,13 @@
|
||||
$select.append('<option value="' + value.id + '">' + value.text + '</option>');
|
||||
});
|
||||
$select.val(originalValues[sel.name]);
|
||||
// Refresh selectpicker updated
|
||||
// Refresh selectpicker if item is such
|
||||
if($select.hasClass('selectpicker'))
|
||||
$select.selectpicker('refresh');
|
||||
// Trigger change for the changed item
|
||||
$select.trigger('change');
|
||||
|
||||
});
|
||||
//triggerChangeSequentially();
|
||||
});
|
||||
};
|
||||
};
|
||||
@ -149,6 +140,7 @@
|
||||
$(formSelector + ' [name="' + f.name + '"]').on('change', onChange(f));
|
||||
});
|
||||
|
||||
// Trigger first filler if it exists, this will cascade rest of "changes" if they exists
|
||||
if( fillers.length )
|
||||
$(formSelector + ' [name="' + fillers[0].name + '"]').trigger('change');
|
||||
};
|
||||
@ -173,15 +165,53 @@
|
||||
return res;
|
||||
};
|
||||
|
||||
gui.forms.launchModal = function(title, fields, item, onSuccess) {
|
||||
// Options has this keys:
|
||||
// title
|
||||
// fields
|
||||
// item
|
||||
// success
|
||||
// buttons: Array of buttons to be added to footer, with:
|
||||
// text --> text of button
|
||||
// css --> button style (btn-default, btn-warning, ...). If not defined, 'btn-default' will be used
|
||||
// action --> function to be executed. Will be passed 3 parameters: event, formSelector and closeFnc
|
||||
// (use gui.forms.read(form selector) to get fields, closeFnc() to close form if desired)
|
||||
// Failed operations will show a modal with server error
|
||||
gui.forms.launchModal = function(options, onSuccess) {
|
||||
options = options || {};
|
||||
|
||||
var id = 'modal-' + Math.random().toString().split('.')[1]; // Get a random ID for this modal
|
||||
var ff = gui.forms.fromFields(fields, item);
|
||||
gui.appendToWorkspace(gui.modal(id, title, ff.html));
|
||||
var ff = gui.forms.fromFields(options.fields, options.item);
|
||||
var footer = '';
|
||||
var clickEventHandlers = [];
|
||||
|
||||
if( options.buttons ) {
|
||||
$.each(options.buttons, function(index, value){
|
||||
var _id = id + '-footer-' + index;
|
||||
var css = value.css || 'btn-default';
|
||||
clickEventHandlers.push({id: '#' + _id, action: value.action });
|
||||
footer += '<button id="' + _id + '" type="button" class="pull-left btn ' + css + '">' + value.text + '</button>';
|
||||
});
|
||||
}
|
||||
gui.appendToWorkspace(gui.modal(id, options.title, ff.html, { footer: footer }));
|
||||
id = '#' + id; // for jQuery
|
||||
|
||||
var formSelector = id + ' form';
|
||||
var closeFnc = function(){$(id).modal('hide');};
|
||||
|
||||
if( ff.init )
|
||||
ff.init(id);
|
||||
|
||||
// Append click events for custom buttons on footer
|
||||
$.each(clickEventHandlers, function(undefined, value){
|
||||
if( value.action ) {
|
||||
$(value.id).on('click', function(event){
|
||||
if( value.action(event, formSelector, closeFnc) == true ) {
|
||||
$(id).modal('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get form
|
||||
var $form = $(id + ' form');
|
||||
|
||||
@ -214,11 +244,11 @@
|
||||
$(id + ' .button-accept').click(function(){
|
||||
if( !$form.valid() )
|
||||
return;
|
||||
if( onSuccess ) {
|
||||
onSuccess(id + ' form', function(){$(id).modal('hide');}); // Delegate close to to onSuccess
|
||||
if( options.success ) {
|
||||
options.success(formSelector, closeFnc); // Delegate close to to onSuccess
|
||||
return;
|
||||
} else {
|
||||
$(id).modal('hide');
|
||||
closeFnc();
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -97,19 +97,23 @@
|
||||
});
|
||||
};
|
||||
|
||||
gui.modal = function(id, title, content, actionButton, closeButton) {
|
||||
gui.modal = function(id, title, content, options) {
|
||||
options = options || {};
|
||||
return api.templates.evaluate('tmpl_modal', {
|
||||
id: id,
|
||||
title: title,
|
||||
content: content,
|
||||
button1: closeButton,
|
||||
button2: actionButton
|
||||
footer: options.footer,
|
||||
button1: options.closeButton,
|
||||
button2: options.actionButton,
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
gui.launchModal = function(title, content, actionButton, closeButton) {
|
||||
gui.launchModal = function(title, content, options) {
|
||||
options = options || {};
|
||||
var id = Math.random().toString().split('.')[1]; // Get a random ID for this modal
|
||||
gui.appendToWorkspace(gui.modal(id, title, content, actionButton, closeButton));
|
||||
gui.appendToWorkspace(gui.modal(id, title, content, options));
|
||||
id = '#' + id; // for jQuery
|
||||
|
||||
$(id).modal()
|
||||
@ -130,7 +134,7 @@
|
||||
|
||||
gui.failRequestModalFnc = function(title) {
|
||||
return function(jqXHR, textStatus, errorThrown) { // fail on put
|
||||
gui.launchModal(title, jqXHR.responseText, ' ');
|
||||
gui.launchModal(title, jqXHR.responseText, { actionButton: ' '});
|
||||
};
|
||||
};
|
||||
|
||||
@ -144,35 +148,56 @@
|
||||
};
|
||||
|
||||
// Links methods
|
||||
|
||||
gui.deployed_services = function() {
|
||||
gui.clearWorkspace();
|
||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Deployed services')));
|
||||
};
|
||||
|
||||
// Clean up several "internal" data
|
||||
// I have discovered some "items" that are keep in memory, or that adds garbage to body (datatable && tabletools mainly)
|
||||
// This place is where i add them to "clean" at least those things on page change
|
||||
gui.cleanup = function() {
|
||||
gui.doLog('Cleaning up things');
|
||||
// Tabletools creates divs at end that do not get removed, here is a good place to ensure there is no garbage left behind
|
||||
// And anyway, if this div does not exists, it creates a new one...
|
||||
$('.DTTT_dropdown').remove(); // Tabletools keep adding garbage to end of body on each new table creation, so we simply remove it on each new creation
|
||||
|
||||
// Destroy any created datatable
|
||||
$.each($.fn.dataTable.fnTables(), function(undefined, tbl){
|
||||
$(tbl).dataTable().fnDestroy();
|
||||
});
|
||||
};
|
||||
|
||||
gui.setLinksEvents = function() {
|
||||
var sidebarLinks = [
|
||||
{
|
||||
id : 'lnk-dashboard',
|
||||
exec : gui.dashboard.link,
|
||||
cleanup: true,
|
||||
}, {
|
||||
id : 'lnk-service_providers',
|
||||
exec : gui.providers.link
|
||||
exec : gui.providers.link,
|
||||
cleanup: true,
|
||||
}, {
|
||||
id : 'lnk-authenticators',
|
||||
exec : gui.authenticators.link
|
||||
exec : gui.authenticators.link,
|
||||
cleanup: true,
|
||||
}, {
|
||||
id : 'lnk-osmanagers',
|
||||
exec : gui.osmanagers.link
|
||||
exec : gui.osmanagers.link,
|
||||
cleanup: true,
|
||||
}, {
|
||||
id : 'lnk-connectivity',
|
||||
exec : gui.connectivity.link
|
||||
exec : gui.connectivity.link,
|
||||
cleanup: true,
|
||||
}, {
|
||||
id : 'lnk-deployed_services',
|
||||
exec : gui.deployed_services
|
||||
exec : gui.deployed_services,
|
||||
cleanup: true,
|
||||
}, {
|
||||
id : 'lnk-clear_cache',
|
||||
exec : gui.clear_cache.link,
|
||||
cleanup: false,
|
||||
},
|
||||
];
|
||||
$.each(sidebarLinks, function(index, value) {
|
||||
@ -182,10 +207,10 @@
|
||||
if ($('.navbar-toggle').css('display') != 'none') {
|
||||
$(".navbar-toggle").trigger("click");
|
||||
}
|
||||
if( value.cleanup ) {
|
||||
gui.cleanup();
|
||||
}
|
||||
$('html, body').scrollTop(0);
|
||||
// Tabletools creates divs at end that do not get removed, here is a good place to ensure there is no garbage left behind
|
||||
// And anyway, if this div does not exists, it creates a new one...
|
||||
$('.DTTT_dropdown').remove();
|
||||
value.exec(event);
|
||||
});
|
||||
});
|
||||
@ -223,45 +248,56 @@
|
||||
gui.methods = {};
|
||||
|
||||
// "Generic" edit method to set onEdit table
|
||||
gui.methods.typedEdit = function(parent, modalTitle, modalErrorMsg, guiProcessor, fieldsProcessor) {
|
||||
gui.methods.typedEdit = function(parent, modalTitle, modalErrorMsg, options) {
|
||||
options = options || {}
|
||||
var self = parent;
|
||||
return function(value, event, table, refreshFnc) {
|
||||
self.rest.gui(value.type, function(guiDefinition) {
|
||||
var tabs = guiProcessor ? guiProcessor(guiDefinition) : guiDefinition; // Preprocess fields (probably generate tabs...)
|
||||
var tabs = options.guiProcessor ? options.guiProcessor(guiDefinition) : guiDefinition; // Preprocess fields (probably generate tabs...)
|
||||
self.rest.item(value.id, function(item) {
|
||||
gui.forms.launchModal(modalTitle+' <b>'+value.name+'</b>', tabs, item, function(form_selector, closeFnc) {
|
||||
gui.forms.launchModal({
|
||||
title: modalTitle+' <b>'+value.name+'</b>',
|
||||
fields: tabs,
|
||||
item: item,
|
||||
buttons: options.buttons,
|
||||
success: function(form_selector, closeFnc) {
|
||||
var fields = gui.forms.read(form_selector);
|
||||
fields.data_type = value.type;
|
||||
fields = fieldsProcessor ? fieldsProcessor(fields) : fields;
|
||||
fields = options.fieldsProcessor ? options.fieldsProcessor(fields) : fields;
|
||||
self.rest.save(fields, function(data) { // Success on put
|
||||
closeFnc();
|
||||
refreshFnc();
|
||||
gui.alert(gettext('Edition successfully done'), 'success');
|
||||
}, gui.failRequestModalFnc(modalErrorMsg)); // Fail on put, show modal message
|
||||
return false;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
}, gui.failRequestModalFnc(modalErrorMsg));
|
||||
};
|
||||
};
|
||||
|
||||
// "Generic" new method to set onNew table
|
||||
gui.methods.typedNew = function(parent, modalTitle, modalErrorMsg, guiProcessor, fieldsProcessor) {
|
||||
gui.methods.typedNew = function(parent, modalTitle, modalErrorMsg, options) {
|
||||
options = options || {};
|
||||
var self = parent;
|
||||
return function(type, table, refreshFnc) {
|
||||
self.rest.gui(type, function(guiDefinition) {
|
||||
var tabs = guiProcessor ? guiProcessor(guiDefinition) : guiDefinition; // Preprocess fields (probably generate tabs...)
|
||||
gui.forms.launchModal(modalTitle, tabs, undefined, function(form_selector, closeFnc) {
|
||||
var tabs = options.guiProcessor ? options.guiProcessor(guiDefinition) : guiDefinition; // Preprocess fields (probably generate tabs...)
|
||||
gui.forms.launchModal({
|
||||
title: modalTitle,
|
||||
fields: tabs,
|
||||
item: undefined,
|
||||
buttons: options.buttons,
|
||||
success: function(form_selector, closeFnc) {
|
||||
var fields = gui.forms.read(form_selector);
|
||||
fields.data_type = type;
|
||||
fields = fieldsProcessor ? fieldsProcessor(fields) : fields; // P
|
||||
fields = options.fieldsProcessor ? options.fieldsProcessor(fields) : fields; // Process fields before creating?
|
||||
self.rest.create(fields, function(data) { // Success on put
|
||||
closeFnc();
|
||||
refreshFnc();
|
||||
gui.alert(gettext('Creation successfully done'), 'success');
|
||||
}, gui.failRequestModalFnc(modalErrorMsg) // Fail on put, show modal message
|
||||
);
|
||||
}, gui.failRequestModalFnc(modalErrorMsg)); // Fail on put, show modal message
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -271,7 +307,7 @@
|
||||
var self = parent;
|
||||
return function(value, event, table, refreshFnc) {
|
||||
var content = gettext('Are you sure do you want to delete ') + '<b>' + value.name + '</b>';
|
||||
var modalId = gui.launchModal(modalTitle, content, '<button type="button" class="btn btn-danger button-accept">' + gettext('Delete') + '</button>');
|
||||
var modalId = gui.launchModal(modalTitle, content, { actionButton: '<button type="button" class="btn btn-danger button-accept">' + gettext('Delete') + '</button>'});
|
||||
$(modalId + ' .button-accept').click(function(){
|
||||
$(modalId).modal('hide');
|
||||
self.rest.del(value.id, function(){
|
||||
|
@ -11,6 +11,7 @@
|
||||
{{{ content }}}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{{{ footer }}}
|
||||
{{# if button1 }}
|
||||
{{{ button1 }}}
|
||||
{{ else }}
|
||||
|
Loading…
Reference in New Issue
Block a user