diff --git a/server/src/uds/REST/methods/services.py b/server/src/uds/REST/methods/services.py
index ca042c49..c2f37251 100644
--- a/server/src/uds/REST/methods/services.py
+++ b/server/src/uds/REST/methods/services.py
@@ -34,8 +34,9 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext as _
-from uds.core.Environment import Environment
+from uds.models import Service
+from uds.core.Environment import Environment
from uds.REST.model import DetailHandler
from uds.REST import NotFound, ResponseError, RequestError
from django.db import IntegrityError
@@ -77,6 +78,7 @@ class Services(DetailHandler):
def saveItem(self, parent, item):
# Extract item db fields
# We need this fields for all
+ logger.debug('Saving service {0} / {1}'.format(parent, item))
fields = self.readFieldsFromParams(['name', 'comments', 'data_type'])
try:
if item is None: # Create new
@@ -87,11 +89,12 @@ class Services(DetailHandler):
service.data = service.getInstance(self._params).serialize()
service.save()
- except self.model.DoesNotExist:
+ except Service.DoesNotExist:
raise NotFound('Item not found')
except IntegrityError: # Duplicate key probably
raise RequestError('Element already exists (duplicate key error)')
except Exception:
+ logger.exception('Saving Service')
raise RequestError('incorrect invocation to PUT')
return self.getItems(parent, service.id)
diff --git a/server/src/uds/REST/model.py b/server/src/uds/REST/model.py
index 4307cc65..17a92730 100644
--- a/server/src/uds/REST/model.py
+++ b/server/src/uds/REST/model.py
@@ -260,6 +260,7 @@ class DetailHandler(BaseModelHandler):
# Default save
def saveItem(self, parent, item):
+ logger.debug('Default saveItem handler caller for {0}'.format(self._path))
self.invalidRequestException()
# Default delete
@@ -354,9 +355,11 @@ class ModelHandler(BaseModelHandler):
args = list(self._args[2:])
path = self._path + '/'.join(args[:2])
detail = detailCls(self, path, self._params, *args, parent = item)
- return getattr(detail, self._operation)()
+ method = getattr(detail, self._operation)
except AttributeError:
raise NotFound('method not found')
+
+ return method()
def getItems(self, *args, **kwargs):
for item in self.model.objects.filter(*args, **kwargs):
diff --git a/server/src/uds/static/adm/css/uds-admin.css b/server/src/uds/static/adm/css/uds-admin.css
index c14fb22e..3fbaf3b3 100644
--- a/server/src/uds/static/adm/css/uds-admin.css
+++ b/server/src/uds/static/adm/css/uds-admin.css
@@ -70,6 +70,14 @@ table.dataTable tr.even td.sorting_3 { background-color: blue; }*/
}
+/*.modal-backdrop {
+ background-color: gray;
+}*/
+
+.modal {
+ overflow-y: auto;
+}
+
.tab-pane {
margin-top: 24px;
}
diff --git a/server/src/uds/static/adm/js/api-tools.js b/server/src/uds/static/adm/js/api-tools.js
index 809b4b40..af2bf192 100644
--- a/server/src/uds/static/adm/js/api-tools.js
+++ b/server/src/uds/static/adm/js/api-tools.js
@@ -1,57 +1,14 @@
/* jshint strict: true */
-(function(tools, $, undefined) {
+(function(api, $, undefined) {
"use strict";
- tools.base64 = function(s) {
- return window.btoa(unescape(encodeURIComponent(s)));
+
+ api.tools = {
+ base64 : function(s) {
+ return window.btoa(unescape(encodeURIComponent(s)));
+ }
};
- tools.fix3dButtons = function(selector) {
- selector = selector || '';
- selector += ' .btn3d';
- console.log(selector);
- $.each($(selector), function(index, value) {
- var $this = $(this);
-
- var clkEvents = [];
-
- // Store old click events, so we can reconstruct click chain later
- $.each($._data(value, 'events').click, function(index, fnc) {
- clkEvents.push(fnc);
- });
- $this.unbind('click');
-
- /* If Mousedown registers a temporal mouseUp event on parent, to lauch button click */
- $this.mousedown(function(event){
- $('body').mouseup(function(e){
- // Remove temporal mouseup handler
- $(this).unbind('mouseup');
-
- // If movement of mouse is not too far... (16 px maybe well for 3d buttons?)
- var x = event.pageX - e.pageX, y = event.pageY - e.pageY;
- var dist_square = x*x + y*y;
- if( dist_square < 16*16 ) {
- // Register again old event handlers
- $.each(clkEvents, function(index, fnc){
- $this.click(fnc.handler);
- });
- $this.click();
- $this.unbind('click');
- }
- });
- });
- });
- };
-
- tools.blockUI = function(message) {
- message = message || '
' + gettext('Just a moment...') + '
';
- $.blockUI({ message: message });
- };
-
- tools.unblockUI = function() {
- $.unblockUI();
- };
-
-}(api.tools = api.tools || {}, jQuery));
+}(window.api = window.api || {}, jQuery));
// Insert strftime into tools
@@ -68,7 +25,6 @@
;(function() {
"use strict";
- api.tools = api.tools || {};
var namespace = api.tools;
diff --git a/server/src/uds/static/adm/js/dataTables.bootstrap.js b/server/src/uds/static/adm/js/dataTables.bootstrap.js
index 9e90f989..a1f38d1f 100644
--- a/server/src/uds/static/adm/js/dataTables.bootstrap.js
+++ b/server/src/uds/static/adm/js/dataTables.bootstrap.js
@@ -133,6 +133,10 @@ if ($.fn.DataTable.TableTools) {
"row" : "active"
}
});
+
+ $.extend(true, $.fn.DataTable.TableTools.DEFAULTS, {
+ "aButtons": [],
+ });
// Have the collection use a bootstrap compatible dropdown
$.extend(true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
diff --git a/server/src/uds/static/adm/js/gui-definition.js b/server/src/uds/static/adm/js/gui-definition.js
index ffb4f9fc..f7e811b3 100644
--- a/server/src/uds/static/adm/js/gui-definition.js
+++ b/server/src/uds/static/adm/js/gui-definition.js
@@ -21,7 +21,7 @@ gui.dashboard.link = function(event) {
});
});
- api.tools.fix3dButtons('#test');
+ gui.tools.fix3dButtons('#test');
});
};
@@ -33,7 +33,7 @@ gui.providers.link = function(event) {
// Button definition to trigger "Test" action
var testButton = {
testButton: {
- text: gettext('Test provider'),
+ text: gettext('Test'),
css: 'btn-info',
},
};
@@ -62,7 +62,7 @@ gui.providers.link = function(event) {
return true;
},
onRowSelect : function(selected) {
- api.tools.blockUI();
+ gui.tools.blockUI();
gui.doLog(selected[0]);
$.each(prevTables, function(undefined, tbl){
@@ -91,12 +91,12 @@ gui.providers.link = function(event) {
return true;
},
buttons : [ 'new', 'edit', 'delete', 'xls' ],
- onEdit : gui.methods.typedEdit(services, gettext('Edit service'), gettext('Error processing service')),
- onNew : gui.methods.typedNew(services, gettext('New service'), gettext('Error creating service')),
- onDelete: gui.methods.del(services, gettext('Delete service'), gettext('Error deleting service')),
+ onEdit : gui.methods.typedEdit(services, gettext('Edit service'), gettext('Error processing service'), testButton),
+ onNew : gui.methods.typedNew(services, gettext('New service'), gettext('Error creating service'), testButton),
+ onDelete: gui.methods.del(services, gettext('Delete service'), gettext('Error deleting service'), testButton),
scrollToTable : false,
onLoad: function(k) {
- api.tools.unblockUI();
+ gui.tools.unblockUI();
},
});
@@ -160,7 +160,7 @@ gui.authenticators.link = function(event) {
prevTables = [];
- api.tools.blockUI();
+ gui.tools.blockUI();
var id = selected[0].id;
var user = new GuiElement(api.authenticators.detail(id, 'users'), 'users');
var group = new GuiElement(api.authenticators.detail(id, 'groups'), 'groups');
@@ -169,16 +169,18 @@ gui.authenticators.link = function(event) {
rowSelect : 'multi',
buttons : [ 'edit', 'delete', 'xls' ],
onLoad: function(k) {
- api.tools.unblockUI();
+ gui.tools.unblockUI();
},
});
+ // Use defered rendering for users, this table can be "huge"
var usrTable = user.table({
container : 'users-placeholder',
rowSelect : 'multi',
buttons : [ 'new', 'edit', 'delete', 'xls' ],
+ deferedRender: true,
scrollToTable : false,
onLoad: function(k) {
- api.tools.unblockUI();
+ gui.tools.unblockUI();
},
});
diff --git a/server/src/uds/static/adm/js/gui-element.js b/server/src/uds/static/adm/js/gui-element.js
index c1c5090a..6c7ea16e 100644
--- a/server/src/uds/static/adm/js/gui-element.js
+++ b/server/src/uds/static/adm/js/gui-element.js
@@ -50,6 +50,7 @@ GuiElement.prototype = {
// buttons: array of visible buttons (strings), valid are [ 'new', 'edit', 'refresh', 'delete', 'xls' ],
// rowSelect: type of allowed row selection, valid values are 'single' and 'multi'
// scrollToTable: if True, will scroll page to show table
+ // deferedRender: if True, datatable will be created with "bDeferRender": true, that will improve a lot creation
//
// onLoad: Event (function). If defined, will be invoked when table is fully loaded.
// Receives 1 parameter, that is the gui element (GuiElement) used to render table
@@ -214,14 +215,14 @@ GuiElement.prototype = {
// Clears selection first
TableTools.fnGetInstance(tableId).fnSelectNone();
//if( data.length > 1000 )
- api.tools.blockUI();
+ gui.tools.blockUI();
self.rest.overview(function(data) { // Restore overview
setTimeout( function() {
tbl.fnClearTable();
tbl.fnAddData(data);
onRefresh(self);
- api.tools.unblockUI();
+ gui.tools.unblockUI();
}, 0);
}); // End restore overview
return false; // This may be used on button or href, better disable execution of it
@@ -390,14 +391,10 @@ GuiElement.prototype = {
// Initializes oTableTools
var oTableTools = {
- "aButtons" : btns
+ "aButtons" : btns,
+ "sRowSelect": options.rowSelect || 'single',
};
- // Type of row selection
- if (options.rowSelect) {
- oTableTools.sRowSelect = options.rowSelect;
- }
-
if (options.onRowSelect) {
var rowSelectedFnc = options.onRowSelect;
oTableTools.fnRowSelected = function() {
@@ -420,10 +417,10 @@ GuiElement.prototype = {
// second row is lower
// (pagination) row
"sDom" : "<'row'<'col-xs-8'T><'col-xs-4'f>r>t<'row'<'col-xs-5'i><'col-xs-7'p>>",
-
+ "bDeferRender": options.deferedRender || false,
});
// Fix 3dbuttons
- api.tools.fix3dButtons('#' + tableId + '_wrapper .btn-group-3d');
+ gui.tools.fix3dButtons('#' + tableId + '_wrapper .btn-group-3d');
// Fix form
$('#' + tableId + '_filter input').addClass('form-control');
// Add refresh action to panel
diff --git a/server/src/uds/static/adm/js/gui-form.js b/server/src/uds/static/adm/js/gui-form.js
index bcf7b482..80037387 100644
--- a/server/src/uds/static/adm/js/gui-form.js
+++ b/server/src/uds/static/adm/js/gui-form.js
@@ -154,10 +154,13 @@
$(formSelector + ' .modal_field_data').each(function(i, field) {
var $field = $(field);
if( $field.attr('name') ) { // Is a valid field
+ var name = $field.attr('name');
if( $field.attr('type') == 'checkbox') {
- res[$field.attr('name')] = $field.is(':checked');
+ res[name] = $field.is(':checked');
} else {
- res[$field.attr('name')] = $field.val();
+ res[name] = $field.val();
+ if( res[name] === null && $field.is('select') )
+ res[name] = [];
}
}
});
@@ -205,9 +208,7 @@
$.each(clickEventHandlers, function(undefined, value){
if( value.action ) {
$(value.id).on('click', function(event){
- if( value.action(event, formSelector, closeFnc) == true ) {
- $(id).modal('hide');
- }
+ value.action(event, formSelector, closeFnc);
});
}
});
diff --git a/server/src/uds/static/adm/js/gui-tools.js b/server/src/uds/static/adm/js/gui-tools.js
new file mode 100644
index 00000000..06da69ff
--- /dev/null
+++ b/server/src/uds/static/adm/js/gui-tools.js
@@ -0,0 +1,52 @@
+/* jshint strict: true */
+(function(gui, $, undefined) {
+ "use strict";
+
+ gui.tools = {
+ blockUI : function(message) {
+ message = message || ' ' + gettext('Just a moment...') + '
';
+ $.blockUI({ message: message });
+ },
+ unblockUI : function() {
+ $.unblockUI();
+ $('.DTTT_collection_background').remove();
+ },
+ fix3dButtons : function(selector) {
+ selector = selector || '';
+ selector += ' .btn3d';
+ console.log(selector);
+ $.each($(selector), function(index, value) {
+ var $this = $(this);
+
+ var clkEvents = [];
+
+ // Store old click events, so we can reconstruct click chain later
+ $.each($._data(value, 'events').click, function(index, fnc) {
+ clkEvents.push(fnc);
+ });
+ $this.unbind('click');
+
+ /* If Mousedown registers a temporal mouseUp event on parent, to lauch button click */
+ $this.mousedown(function(event){
+ $('body').mouseup(function(e){
+ // Remove temporal mouseup handler
+ $(this).unbind('mouseup');
+
+ // If movement of mouse is not too far... (16 px maybe well for 3d buttons?)
+ var x = event.pageX - e.pageX, y = event.pageY - e.pageY;
+ var dist_square = x*x + y*y;
+ if( dist_square < 16*16 ) {
+ // Register again old event handlers
+ $.each(clkEvents, function(index, fnc){
+ $this.click(fnc.handler);
+ });
+ $this.click();
+ $this.unbind('click');
+ }
+ });
+ });
+ });
+ },
+ };
+
+}(window.gui = window.gui || {}, jQuery));
\ No newline at end of file
diff --git a/server/src/uds/static/adm/js/gui.js b/server/src/uds/static/adm/js/gui.js
index 191b123a..4a612e1e 100644
--- a/server/src/uds/static/adm/js/gui.js
+++ b/server/src/uds/static/adm/js/gui.js
@@ -27,8 +27,8 @@
'oPaginate' : {
'sFirst' : gettext('First'),
'sLast' : gettext('Last'),
- 'sNext' : gettext('Next'),
- 'sPrevious' : gettext('Previous'),
+ 'sNext' : '',
+ 'sPrevious' : '',
}
};
@@ -123,18 +123,15 @@
return id;
};
- gui.alert = function(message, type) {
- api.templates.get('alert', function(tmpl) {
- $(api.templates.evaluate(tmpl, {
- type: type,
- message: message
- })).appendTo('#alerts');
- });
+ gui.notify = function(message, type) {
+ gui.launchModal('' + gettext('Message') + '', '' + message + '', {actionButton: ' '});
};
- gui.failRequestModalFnc = function(title) {
+ gui.failRequestModalFnc = function(title, unblock) {
return function(jqXHR, textStatus, errorThrown) { // fail on put
- gui.launchModal(title, jqXHR.responseText, { actionButton: ' '});
+ if( unblock )
+ gui.tools.unblockUI();
+ gui.launchModal('' + title + '', jqXHR.responseText, { actionButton: ' '});
};
};
@@ -262,8 +259,8 @@
gui.doLog('Fields: ', fields);
rest.test(type, fields, function(data){
gui.launchModal(gettext('Test result'), data, { actionButton: ' '});
- }, gui.failRequestModalFnc(gettext('Test error')))
- }
+ }, gui.failRequestModalFnc(gettext('Test error')));
+ },
},
];
};
@@ -272,6 +269,7 @@
gui.methods.typedEdit = function(parent, modalTitle, modalErrorMsg, options) {
options = options || {};
return function(value, event, table, refreshFnc) {
+ gui.tools.blockUI();
parent.rest.gui(value.type, function(guiDefinition) {
var buttons;
if( options.testButton ) {
@@ -279,6 +277,7 @@
}
var tabs = options.guiProcessor ? options.guiProcessor(guiDefinition) : guiDefinition; // Preprocess fields (probably generate tabs...)
parent.rest.item(value.id, function(item) {
+ gui.tools.unblockUI();
gui.forms.launchModal({
title: modalTitle+' '+value.name+'',
fields: tabs,
@@ -291,12 +290,12 @@
parent.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
+ gui.notify(gettext('Edition successfully done'), 'success');
+ }, gui.failRequestModalFnc(modalErrorMsg, true)); // Fail on put, show modal message
},
});
});
- }, gui.failRequestModalFnc(modalErrorMsg));
+ }, gui.failRequestModalFnc(modalErrorMsg, true));
};
};
@@ -305,7 +304,9 @@
options = options || {};
var self = parent;
return function(type, table, refreshFnc) {
+ gui.tools.blockUI();
self.rest.gui(type, function(guiDefinition) {
+ gui.tools.unblockUI();
var buttons;
if( options.testButton ) {
buttons = gui.methods.typedTestButton(parent.rest, options.testButton.text, options.testButton.css, type);
@@ -323,11 +324,11 @@
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.notify(gettext('Creation successfully done'), 'success');
+ }, gui.failRequestModalFnc(modalErrorMsg, true)); // Fail on put, show modal message
},
});
- });
+ }, gui.failRequestModalFnc(modalErrorMsg, true));
};
};
@@ -340,7 +341,7 @@
$(modalId).modal('hide');
self.rest.del(value.id, function(){
refreshFnc();
- gui.alert(gettext('Deletion successfully done'), 'success');
+ gui.notify(gettext('Item deleted'), 'success');
}, gui.failRequestModalFnc(modalErrorMsg) );
});
};
diff --git a/server/src/uds/templates/uds/admin/index.html b/server/src/uds/templates/uds/admin/index.html
index 3694e7b2..f6b6c0d7 100644
--- a/server/src/uds/templates/uds/admin/index.html
+++ b/server/src/uds/templates/uds/admin/index.html
@@ -99,6 +99,7 @@
+