From b7bfecf87ce85f65da8a3da3d9bba90ca2edb4f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez?= Date: Fri, 22 Nov 2013 11:33:54 +0000 Subject: [PATCH] * Fixed Datatables tools width * Refactoring of API (again...) --- server/src/uds/REST/mixins.py | 11 + server/src/uds/static/adm/js/api-templates.js | 2 +- server/src/uds/static/adm/js/api.js | 80 ++- .../uds/static/adm/js/dataTables.bootstrap.js | 2 +- server/src/uds/static/adm/js/gui-elements.js | 38 +- server/src/uds/static/adm/js/gui.js | 549 +++++++++--------- .../templates/uds/admin/tmpl/fld/hidden.html | 2 +- .../uds/templates/uds/admin/tmpl/modal.html | 2 + .../uds/admin/tmpl/responsive-table.html | 10 + .../templates/uds/admin/tmpl/spreadsheet.html | 3 +- .../uds/templates/uds/admin/tmpl/table.html | 2 +- 11 files changed, 375 insertions(+), 326 deletions(-) create mode 100644 server/src/uds/templates/uds/admin/tmpl/responsive-table.html diff --git a/server/src/uds/REST/mixins.py b/server/src/uds/REST/mixins.py index ee5d15f2a..4f7df23eb 100644 --- a/server/src/uds/REST/mixins.py +++ b/server/src/uds/REST/mixins.py @@ -91,12 +91,23 @@ class ModelHandlerMixin(object): def get(self): logger.debug('method GET for {0}, {1}'.format(self.__class__.__name__, self._args)) if len(self._args) == 0: + result = [] + for val in self.model.objects.all(): + res = self.item_as_dict(val) + if hasattr(val, 'getInstance'): + for key, value in val.getInstance().valuesDict().iteritems(): + res[key] = value + result.append(res) + return result + + if self._args[0] == 'overview': return list(self.getItems()) # If has detail and is requesting detail if self.detail is not None and len(self._args) > 1: return self.processDetail() + try: val = self.model.objects.get(pk=self._args[0]) res = self.item_as_dict(val) diff --git a/server/src/uds/static/adm/js/api-templates.js b/server/src/uds/static/adm/js/api-templates.js index 1b069f079..97718694e 100644 --- a/server/src/uds/static/adm/js/api-templates.js +++ b/server/src/uds/static/adm/js/api-templates.js @@ -60,7 +60,7 @@ }; // Simple JavaScript Templating, using HandleBars - api.templates.evaluate = function (str, context) { + api.templates.evaluate = function(str, context) { // Figure out if we're getting a template, or if we need to // load the template - and be sure to cache the result. var cached; diff --git a/server/src/uds/static/adm/js/api.js b/server/src/uds/static/adm/js/api.js index 7e410ce6f..49c501778 100644 --- a/server/src/uds/static/adm/js/api.js +++ b/server/src/uds/static/adm/js/api.js @@ -128,28 +128,50 @@ BasicModelRest.prototype = { }); } }, - get : function(options) { + get : function(success_fnc, options) { "use strict"; options = options || {}; var path = this.getPath; - if (options.id !== undefined) + if ( options.id ) path += '/' + options.id; return this._requestPath(path, { - cacheKey: '.', // Right now, do not cache this - success: options.success, + cacheKey: '.', // Right now, do not cache any "get" method + success: success_fnc, }); }, - types : function(options) { + list: function(success_fnc, options) { // This is "almost" an alias for get + "use strict"; + options = options || {}; + return this.get(success_fnc, { + id: '', + }); + }, + overview: function(success_fnc, options) { + "use strict"; + options = options || {}; + return this.get(success_fnc, { + id: 'overview', + }); + }, + item: function(itemId, success_fnc, options) { + "use strict"; + options = options || {}; + return this.get(success_fnc, { + id: itemId, + }); + + }, + types : function(success_fnc, options) { "use strict"; options = options || {}; return this._requestPath(this.typesPath, { cacheKey: 'type', - success: options.success, + success: success_fnc, }); }, - gui: function(typeName, options) { + gui: function(typeName, success_fnc, options) { // GUI returns a dict, that contains: // name: Name of the field // value: value of the field (selected element in choice, text for inputs, etc....) @@ -159,31 +181,18 @@ BasicModelRest.prototype = { var path = [this.typesPath, typeName, 'gui'].join('/'); return this._requestPath(path, { cacheKey: typeName + '-gui', - success: options.success, + success: success_fnc, }); }, - tableInfo : function(options) { + tableInfo : function(success_fnc, options) { "use strict"; options = options || {}; - var success_fnc = options.success || function(){api.doLog('success not provided for tableInfo');}; + success_fnc = success_fnc || function(){api.doLog('success not provided for tableInfo');}; var path = this.tableInfoPath; - // Cache types locally, will not change unless new broker version - if( this.cache.get(path) ) { - if (success_fnc) { - success_fnc(this.cache.get(path)); - } - return; - } - - var $this = this; - api.getJson(path, { - success: function(data) { - $this.cache.put(path, data); - success_fnc(data); - }, + this._requestPath(path, { + success: success_fnc, }); - }, detail: function(id, child) { @@ -209,14 +218,27 @@ DetailModelRestApi.prototype = { "use strict"; return this.base.get(options); }, - types: function(options) { - "use strict"; - return this.base.types(options); - }, tableInfo: function(options) { "use strict"; return this.base.tableInfo(options); }, + list: function(success_fnc, options) { // This is "almost" an alias for get + "use strict"; + return this.base.list(success_fnc, options); + }, + overview: function(success_fnc, options) { + "use strict"; + return this.base.overview(success_fnc, options); + }, + item: function(itemId, success_fnc, options) { + "use strict"; + return this.base.item(success_fnc, options); + }, + types: function(options) { + "use strict"; + return this.base.types(options); + }, + }; // Populate api diff --git a/server/src/uds/static/adm/js/dataTables.bootstrap.js b/server/src/uds/static/adm/js/dataTables.bootstrap.js index 32dded492..0be29fa7b 100644 --- a/server/src/uds/static/adm/js/dataTables.bootstrap.js +++ b/server/src/uds/static/adm/js/dataTables.bootstrap.js @@ -139,6 +139,6 @@ if ($.fn.DataTable.TableTools) { "button" : "li", "liner" : "a" }, - "button" : "button", +// "button" : "button", }); } diff --git a/server/src/uds/static/adm/js/gui-elements.js b/server/src/uds/static/adm/js/gui-elements.js index 35b6c0015..d9155a575 100644 --- a/server/src/uds/static/adm/js/gui-elements.js +++ b/server/src/uds/static/adm/js/gui-elements.js @@ -35,17 +35,14 @@ gui.providers.link = function(event) { var tableId = gui.providers.table({ rowSelect : 'single', onEdit: function(value, event, table) { - gui.providers.rest.gui(value.type, { - success: function(data){ + gui.providers.rest.gui(value.type, function(data) { var form = gui.fields(data); gui.appendToWorkspace(gui.modal('edit_modal', gettext('Edit service provider'), form)); $('#edit_modal').modal() .on('hidden.bs.modal', function () { $('#edit_modal').remove(); - }) -; - }, - }); + }); + }); }, buttons : [ 'edit', 'delete', 'xls' ], }); @@ -90,7 +87,7 @@ gui.authenticators.link = function(event) { user.table({ container : 'users-placeholder', rowSelect : 'multi', - buttons : [ 'edit', 'delete', 'xls' ], + buttons : [ 'new', 'edit', 'delete', 'xls' ], scrollToTable : true, onLoad: function(k) { api.tools.unblockUI(); @@ -102,12 +99,10 @@ gui.authenticators.link = function(event) { $('#users-placeholder').empty(); // Remove detail on parent refresh }, onEdit: function(value, event, table) { - gui.authenticators.rest.gui(value.type, { - success: function(data){ + gui.authenticators.rest.gui(value.type, function(data){ var form = gui.fields(data); gui.launchModal(gettext('Edit authenticator')+' '+value.name, form); - }, - }); + }); }, }); }); @@ -146,29 +141,26 @@ gui.connectivity.link = function(event) { gui.connectivity.transports.table({ rowSelect : 'multi', container : 'transports-placeholder', - buttons : [ 'edit', 'delete', 'xls' ], + buttons : [ 'new', 'edit', 'delete', 'xls' ], onEdit: function(value, event, table) { - gui.connectivity.transports.rest.gui(value.type, { - success: function(itemGui){ - gui.connectivity.transports.rest.get({ - id:value.id, - success: function(item) { + gui.connectivity.transports.rest.gui(value.type, function(itemGui){ + gui.connectivity.transports.rest.item(value.id, function(item) { var form = gui.fields(itemGui, item); gui.launchModal(gettext('Edit transport')+' '+value.name,form, function(form_selector) { var fields = gui.fields.read(form_selector); return false; }); - }, - }); - }, - }); + }); + }); + }, + onNew: function(type) { + gui.doLog(type); }, - }); gui.connectivity.networks.table({ rowSelect : 'multi', container : 'networks-placeholder', - buttons : [ 'edit', 'delete', 'xls' ], + buttons : [ 'new', 'edit', 'delete', 'xls' ], }); }); diff --git a/server/src/uds/static/adm/js/gui.js b/server/src/uds/static/adm/js/gui.js index 6c7052897..b0046d083 100644 --- a/server/src/uds/static/adm/js/gui.js +++ b/server/src/uds/static/adm/js/gui.js @@ -2,10 +2,10 @@ (function(gui, $, undefined) { "use strict"; // "public" methods - gui.doLog = function(data) { + gui.doLog = function() { if (gui.debug) { try { - console.log(data); + console.log(arguments); } catch (e) { // nothing can be logged } @@ -212,8 +212,7 @@ GuiElement.prototype = { "use strict"; gui.doLog('Initializing ' + this.name); var $this = this; - this.rest.types({ - success: function(data) { + this.rest.types(function(data) { var styles = ''; $.each(data, function(index, value) { var className = $this.name + '-' + value.type; @@ -231,8 +230,7 @@ GuiElement.prototype = { styles = ''; $(styles).appendTo('head'); } - }, - }); + }); }, // Options: dictionary // container: container ID of parent for the table. If undefined, table will be appended to workspace @@ -268,6 +266,7 @@ GuiElement.prototype = { // 4.- the DataTable that raised the event table : function(options) { "use strict"; + console.log('Types: ', this.types); options = options || {}; gui.doLog('Composing table for ' + this.name); var tableId = this.name + '-table'; @@ -313,287 +312,301 @@ GuiElement.prototype = { return dict[data] || renderEmptyCell(''); }; }; - this.rest.tableInfo({ - success: function(data) { - var title = data.title; - var columns = []; - $.each(data.fields, function(index, value) { - for ( var v in value) { - var opts = value[v]; - var column = { - mData : v, - }; - column.sTitle = opts.title; - column.mRender = renderEmptyCell; - if (opts.width) - column.sWidth = opts.width; - column.bVisible = opts.visible === undefined ? true : opts.visible; - if (opts.sortable !== undefined) - column.bSortable = opts.sortable; - if (opts.searchable !== undefined) - column.bSearchable = opts.searchable; - - if (opts.type !== undefined && column.bVisible ) { - switch(opts.type) { - case 'date': - column.sType = 'date'; - column.mRender = renderDate(api.tools.djangoFormat(get_format('SHORT_DATE_FORMAT'))); - break; - case 'datetime': - column.sType = 'date'; - column.mRender = renderDate(api.tools.djangoFormat(get_format('SHORT_DATETIME_FORMAT'))); - break; - case 'time': - column.mRender = renderDate(api.tools.djangoFormat(get_format('TIME_FORMAT'))); - break; - case 'iconType': - //columnt.sType = 'html'; // html is default, so this is not needed - column.mRender = renderTypeIcon; - break; - case 'icon': - if( opts.icon !== undefined ) { - column.mRender = renderIcon(opts.icon); - } - break; - case 'dict': - if( opts.dict !== undefined ) { - column.mRender = renderTextTransform(opts.dict); - } - break; - default: - column.sType = opts.type; - } + this.rest.tableInfo(function(data) { + var title = data.title; + var columns = []; + $.each(data.fields, function(index, value) { + for ( var v in value) { + var opts = value[v]; + var column = { + mData : v, + }; + column.sTitle = opts.title; + column.mRender = renderEmptyCell; + if (opts.width) + column.sWidth = opts.width; + column.bVisible = opts.visible === undefined ? true : opts.visible; + if (opts.sortable !== undefined) + column.bSortable = opts.sortable; + if (opts.searchable !== undefined) + column.bSearchable = opts.searchable; + + if (opts.type && column.bVisible ) { + switch(opts.type) { + case 'date': + column.sType = 'date'; + column.mRender = renderDate(api.tools.djangoFormat(get_format('SHORT_DATE_FORMAT'))); + break; + case 'datetime': + column.sType = 'date'; + column.mRender = renderDate(api.tools.djangoFormat(get_format('SHORT_DATETIME_FORMAT'))); + break; + case 'time': + column.mRender = renderDate(api.tools.djangoFormat(get_format('TIME_FORMAT'))); + break; + case 'iconType': + //columnt.sType = 'html'; // html is default, so this is not needed + column.mRender = renderTypeIcon; + break; + case 'icon': + if( opts.icon !== undefined ) { + column.mRender = renderIcon(opts.icon); + } + break; + case 'dict': + if( opts.dict !== undefined ) { + column.mRender = renderTextTransform(opts.dict); + } + break; + default: + column.sType = opts.type; } - columns.push(column); } - }); - // Generate styles for responsible table, just the name of fields - var respStyles = []; - var counter = 0; - $.each(columns, function(col, value) { - if( value.bVisible === false ) - return; - counter += 1; - respStyles.push('#' + tableId + ' td:nth-of-type(' + counter + '):before { content: "' + - (value.sTitle || '') + '";}\n'); - respStyles.push('#' + tableId + ' td:nth-of-type(' + counter + '):empty { background-color: red ;}\n'); - }); - // If styles already exists, remove them before adding new ones - $('style-' + tableId).remove(); - $('').appendTo('head'); - - $this.rest.get({ - success : function(data) { - var refreshFnc; - var table = gui.table(title, tableId); - if (options.container === undefined) { - gui.appendToWorkspace('
' + table.text + '
'); - } else { - $('#' + options.container).empty(); - $('#' + options.container).append(table.text); - } - - var btns = []; - - if (options.buttons) { - var clickHandlerFor = function(handler, action) { - var handleFnc = handler || function(val, action, tbl) {gui.doLog('Default handler called for ' + action + ': ' + JSON.stringify(val));}; - return function(btn) { - var tbl = $('#' + tableId).dataTable(); - var val = this.fnGetSelectedData()[0]; - setTimeout(function() { - handleFnc(val, action, tbl); - }, 0); - }; - }; + columns.push(column); + } + }); + // Generate styles for responsible table, just the name of fields (append header to table) + var respStyles = []; + var counter = 0; + $.each(columns, function(col, value) { + if( value.bVisible === false ) + return; + counter += 1; + respStyles.push('#' + tableId + ' td:nth-of-type(' + counter + '):before { content: "' + + (value.sTitle || '') + '";}\n'); + }); + // If styles already exists, remove them before adding new ones + $('style-' + tableId).remove(); + $('').appendTo('head'); - // methods for buttons on row select - var editSelected = function(btn, obj, node) { - var sel = this.fnGetSelectedData(); - if (sel.length == 1) { - $(btn).removeClass('disabled').addClass('btn3d-success'); - } else { - $(btn).removeClass('btn3d-success').addClass('disabled'); - } - }; - var deleteSelected = function(btn, obj, node) { - var sel = this.fnGetSelectedData(); - if (sel.length > 0) { - $(btn).removeClass('disabled').addClass('btn3d-warning'); - } else { - $(btn).removeClass('btn3d-warning').addClass('disabled'); - } - }; - - // What execute on refresh button push - var onRefresh = options.onRefresh || function(){}; - - refreshFnc = function() { - // Refreshes table content + $this.rest.overview(function(data) { + var table = gui.table(title, tableId); + if (options.container === undefined) { + gui.appendToWorkspace('
' + table.text + '
'); + } else { + $('#' + options.container).empty(); + $('#' + options.container).append(table.text); + } + + // What execute on refresh button push + var onRefresh = options.onRefresh || function(){}; + + var refreshFnc = function() { + // Refreshes table content + var tbl = $('#' + tableId).dataTable(); + // Clears selection first + TableTools.fnGetInstance(tableId).fnSelectNone(); + if( data.length > 1000 ) + api.tools.blockUI(); + + $this.rest.overview(function(data) { + /*$(btn).removeClass('disabled').width('').html(saved);*/ + setTimeout( function() { + tbl.fnClearTable(); + tbl.fnAddData(data); + onRefresh($this); + api.tools.unblockUI(); + }, 0); + }); + return false; // This may be used on button or href, better disable execution of it + }; + + var btns = []; + + if (options.buttons) { + var clickHandlerFor = function(handler, action, newHandler) { + var handleFnc = handler || function(val, action, tbl) {gui.doLog('Default handler called for ', action);}; + return function(btn) { var tbl = $('#' + tableId).dataTable(); - // Clears selection first - TableTools.fnGetInstance(tableId).fnSelectNone(); - if( data.length > 1000 ) - api.tools.blockUI(); - - $this.rest.get({ - success : function(data) { - /*$(btn).removeClass('disabled').width('').html(saved);*/ - setTimeout( function() { - tbl.fnClearTable(); - tbl.fnAddData(data); - onRefresh($this); - api.tools.unblockUI(); - }, 0); + var val = this.fnGetSelectedData()[0]; + setTimeout(function() { + if( newHandler ) { + if( handleFnc(action, tbl) === true ) // Reload table? + refreshFnc(); + } else { + if( handleFnc(val, action, tbl) === true ) // Reload table? + refreshFnc(); } - }); - return false; // This may be used on button or href, better disable execution of it + }, 0); }; - - $.each(options.buttons, function(index, value) { - var btn; - switch (value) { - case 'new': + }; + + // methods for buttons on row select + var editSelected = function(btn, obj, node) { + var sel = this.fnGetSelectedData(); + if (sel.length == 1) { + $(btn).removeClass('disabled').addClass('btn3d-success'); + } else { + $(btn).removeClass('btn3d-success').addClass('disabled'); + } + }; + var deleteSelected = function(btn, obj, node) { + var sel = this.fnGetSelectedData(); + if (sel.length > 0) { + $(btn).removeClass('disabled').addClass('btn3d-warning'); + } else { + $(btn).removeClass('btn3d-warning').addClass('disabled'); + } + }; + + $.each(options.buttons, function(index, value) { + var btn; + switch (value) { + case 'new': + if(Object.keys($this.types).length === 0) { btn = { "sExtends" : "text", "sButtonText" : gui.config.dataTableButtons['new'].text, - "fnSelect" : deleteSelected, - "fnClick" : clickHandlerFor(options.onDelete, 'delete'), + "fnClick" : clickHandlerFor(options.onNew, 'new'), "sButtonClass" : gui.config.dataTableButtons['new'].css, }; - break; - case 'edit': + } else { + // This table has "types, so we create a dropdown with Types + var newButtons = []; + $.each($this.types, function(i, val){ + newButtons.push({ + "sExtends" : "text", + "sButtonText" : ' ' + val.name, + "fnClick" : clickHandlerFor(options.onNew, i, true), + }); + }); btn = { - "sExtends" : "text", - "sButtonText" : gui.config.dataTableButtons.edit.text, - "fnSelect" : editSelected, - "fnClick" : clickHandlerFor(options.onEdit, 'edit'), - "sButtonClass" : gui.config.dataTableButtons.edit.css, - }; - break; - case 'delete': - btn = { - "sExtends" : "text", - "sButtonText" : gui.config.dataTableButtons['delete'].text, - "fnSelect" : deleteSelected, - "fnClick" : clickHandlerFor(options.onDelete, 'delete'), - "sButtonClass" : gui.config.dataTableButtons['delete'].css, - }; - break; - case 'refresh': - btn = { - "sExtends" : "text", - "sButtonText" : gui.config.dataTableButtons.refresh.text, - "fnClick" : refreshFnc, - "sButtonClass" : gui.config.dataTableButtons.refresh.css, - }; - break; - case 'xls': - btn = { - "sExtends" : "text", - "sButtonText" : gui.config.dataTableButtons.xls.text, - "fnClick" : function(){ - api.templates.get('spreadsheet', function(tmpl) { - var styles = { 'bold': 's21', }; - var uri = 'data:application/vnd.ms-excel;base64,', - base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))); }; - - var headings = [], rows = []; - $.each(columns, function(index, heading){ - if( heading.bVisible === false ) { + "sExtends" : "collection", + "aButtons": newButtons, + "sButtonText" : gui.config.dataTableButtons['new'].text, + "sButtonClass" : gui.config.dataTableButtons['new'].css, + }; + } + break; + case 'edit': + btn = { + "sExtends" : "text", + "sButtonText" : gui.config.dataTableButtons.edit.text, + "fnSelect" : editSelected, + "fnClick" : clickHandlerFor(options.onEdit, 'edit'), + "sButtonClass" : gui.config.dataTableButtons.edit.css, + }; + break; + case 'delete': + btn = { + "sExtends" : "text", + "sButtonText" : gui.config.dataTableButtons['delete'].text, + "fnSelect" : deleteSelected, + "fnClick" : clickHandlerFor(options.onDelete, 'delete'), + "sButtonClass" : gui.config.dataTableButtons['delete'].css, + }; + break; + case 'refresh': + btn = { + "sExtends" : "text", + "sButtonText" : gui.config.dataTableButtons.refresh.text, + "fnClick" : refreshFnc, + "sButtonClass" : gui.config.dataTableButtons.refresh.css, + }; + break; + case 'xls': + btn = { + "sExtends" : "text", + "sButtonText" : gui.config.dataTableButtons.xls.text, + "fnClick" : function(){ + api.templates.get('spreadsheet', function(tmpl) { + var styles = { 'bold': 's21', }; + var uri = 'data:application/vnd.ms-excel;base64,', + base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))); }; + + var headings = [], rows = []; + $.each(columns, function(index, heading){ + if( heading.bVisible === false ) { + return; + } + headings.push(api.spreadsheet.cell(heading.sTitle, 'String', styles.bold)); + }); + rows.push(api.spreadsheet.row(headings)); + $.each(data, function(index, row) { + var cells = []; + $.each(columns, function(index, col){ + if( col.bVisible === false ) { return; } - headings.push(api.spreadsheet.cell(heading.sTitle, 'String', styles.bold)); + var type = col.sType == 'numeric' ? 'Number':'String'; + cells.push(api.spreadsheet.cell(row[col.mData], type)); }); - rows.push(api.spreadsheet.row(headings)); - $.each(data, function(index, row) { - var cells = []; - $.each(columns, function(index, col){ - if( col.bVisible === false ) { - return; - } - var type = col.sType == 'numeric' ? 'Number':'String'; - cells.push(api.spreadsheet.cell(row[col.mData], type)); - }); - rows.push(api.spreadsheet.row(cells)); - }); - - var ctx = { - creation_date: (new Date()).toISOString(), - worksheet: title, - columns_count: headings.length, - rows_count: rows.length, - rows: rows.join('\n') - }; - setTimeout( function() { - saveAs(new Blob([api.templates.evaluate(tmpl, ctx)], - {type: 'application/vnd.ms-excel'} ), title + '.xls'); - }, 20); + rows.push(api.spreadsheet.row(cells)); }); - }, - "sButtonClass" : gui.config.dataTableButtons.xls.css, - }; - } - - if (btn !== undefined) - btns.push(btn); - }); - } - - // Initializes oTableTools - var oTableTools = { - "aButtons" : btns - }; - - // Type of row selection - if (options.rowSelect) { - oTableTools.sRowSelect = options.rowSelect; - } - - if (options.onRowSelect) { - var rowSelectedFnc = options.onRowSelect; - oTableTools.fnRowSelected = function() { - rowSelectedFnc(this.fnGetSelectedData(), $('#' + tableId).dataTable(), this); - }; - } - if (options.onRowDeselect) { - var rowDeselectedFnc = options.onRowDeselect; - oTableTools.fnRowDeselected = function() { - rowDeselectedFnc(this.fnGetSelectedData(), $('#' + tableId).dataTable(), this); - }; - } - - $('#' + tableId).dataTable({ - "aaData" : data, - "aoColumns" : columns, - "oLanguage" : gui.config.dataTablesLanguage, - "oTableTools" : oTableTools, - // First is upper row, - // 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>>", - + + var ctx = { + creation_date: (new Date()).toISOString(), + worksheet: title, + columns_count: headings.length, + rows_count: rows.length, + rows: rows.join('\n') + }; + setTimeout( function() { + saveAs(new Blob([api.templates.evaluate(tmpl, ctx)], + {type: 'application/vnd.ms-excel'} ), title + '.xls'); + }, 20); + }); + }, + "sButtonClass" : gui.config.dataTableButtons.xls.css, + }; + } + + if (btn !== undefined) + btns.push(btn); }); - // Fix 3dbuttons - api.tools.fix3dButtons('#' + tableId + '_wrapper .btn-group-3d'); - // Fix form - $('#' + tableId + '_filter input').addClass('form-control'); - // Add refresh action to panel - $(table.refreshSelector).click(refreshFnc); - - if (options.scrollToTable === true ) { - var tableTop = $('#' + tableId).offset().top; - $('html, body').scrollTop(tableTop); - } - // if table rendered event - if( options.onLoad ) { - options.onLoad($this); - } + } + + // Initializes oTableTools + var oTableTools = { + "aButtons" : btns + }; + + // Type of row selection + if (options.rowSelect) { + oTableTools.sRowSelect = options.rowSelect; + } + + if (options.onRowSelect) { + var rowSelectedFnc = options.onRowSelect; + oTableTools.fnRowSelected = function() { + rowSelectedFnc(this.fnGetSelectedData(), $('#' + tableId).dataTable(), this); + }; + } + if (options.onRowDeselect) { + var rowDeselectedFnc = options.onRowDeselect; + oTableTools.fnRowDeselected = function() { + rowDeselectedFnc(this.fnGetSelectedData(), $('#' + tableId).dataTable(), this); + }; + } + + $('#' + tableId).dataTable({ + "aaData" : data, + "aoColumns" : columns, + "oLanguage" : gui.config.dataTablesLanguage, + "oTableTools" : oTableTools, + // First is upper row, + // 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>>", + + }); + // Fix 3dbuttons + api.tools.fix3dButtons('#' + tableId + '_wrapper .btn-group-3d'); + // Fix form + $('#' + tableId + '_filter input').addClass('form-control'); + // Add refresh action to panel + $(table.refreshSelector).click(refreshFnc); + + if (options.scrollToTable === true ) { + var tableTop = $('#' + tableId).offset().top; + $('html, body').scrollTop(tableTop); + } + // if table rendered event + if( options.onLoad ) { + options.onLoad($this); } }); - }, - - }); + }); return '#' + tableId; } diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html b/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html index f0a4608d3..3d1f3f449 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html @@ -1,3 +1,3 @@ {% verbatim %} - + {% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/modal.html b/server/src/uds/templates/uds/admin/tmpl/modal.html index a7731fcf4..36c99c5a6 100644 --- a/server/src/uds/templates/uds/admin/tmpl/modal.html +++ b/server/src/uds/templates/uds/admin/tmpl/modal.html @@ -9,6 +9,8 @@ +
- +