Bug 24561: Add a Datatables api wrapper that implements filter and order embedded columns

This patch adds the ability to filter and order by embedded columns.

To use it you must in JS:

$('datatable_selector').api({datatables_options})

where datatables_options are all datatables options plus:

1. embed: [list of embeddable tables]
   This option adds x-koha-embed header to request.

2. header_filter: true|false
   This option if true sets x-koha-query header with stringyfied json of filters

Oderable and searchable columns must define data option as string, otherwise filter and order won't be possible.
If you must custom the output, use the render function.

For example:

* Don't

> $('.table_selector').api({
>   columns: [
>     {
>       data: function(row, type, val, meta) {
>         return '<a href="'+row.link+'">'+row.holds.patron.firstname+'</a>';
>       },
>       orderable: true,
>       searchable: true
>     }
>   ]
> });

* Do

> $('.table_selector').api({
>   columns: [
>     {
>       data: 'holds.patron.firstname',
>       render: function(row, type, val, meta) {
>         return '<a href="'+row.link+'">'+row.holds.patron.firstname+'</a>';
>       },
>       orderable: true,
>       searchable: true
>     }
>   ]
> });

To test you must implement and test bug 20936, where it will be used.

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
This commit is contained in:
Agustin Moyano 2020-02-19 11:33:14 -03:00 committed by Martin Renvoize
parent 3f546c031a
commit 4b37a4e8d3
No known key found for this signature in database
GPG Key ID: 422B469130441A0F
2 changed files with 182 additions and 0 deletions

View File

@ -502,3 +502,94 @@ function filterDataTable( table, column, term ){
table.search( term ).draw("page");
}
}
jQuery.fn.dataTable.ext.errMode = function(settings, note, message) {
console.warn(message);
};
(function($) {
$.fn.api = function(options) {
var settings = null;
if(options) {
settings = $.extend(true, {}, dataTablesDefaults, {
'deferRender': true,
"paging": true,
'serverSide': true,
'searching': true,
'pagingType': 'full',
'ajax': {
'type': 'GET',
'cache': true,
'dataSrc': 'data',
'beforeSend': function(xhr, settings) {
this._xhr = xhr;
if(options.embed) {
xhr.setRequestHeader('x-koha-embed', Array.isArray(options.embed)?options.embed.join(','):options.embed);
}
if(options.header_filter && options.query_parameters) {
xhr.setRequestHeader('x-koha-query', options.query_parameters);
delete options.query_parameters;
}
},
'dataFilter': function(data, type) {
var json = {data: JSON.parse(data)};
if(total = this._xhr.getResponseHeader('x-total-count')) {
json.recordsTotal = total;
json.recordsFiltered = total;
}
return JSON.stringify(json);
},
'data': function( data, settings ) {
var length = data.length;
var start = data.start;
var dataSet = {
_page: Math.floor(start/length) + 1,
_per_page: length
};
var filter = data.search.value;
var query_parameters = settings.aoColumns
.filter(function(col) {
return col.bSearchable && typeof col.data == 'string' && (data.columns[col.idx].search.value != '' || filter != '')
})
.map(function(col) {
var part = {};
part[!col.data.includes('.')?'me.'+col.data:col.data] = {like: (data.columns[col.idx].search.value != '' ? data.columns[col.idx].search.value : filter)+'%'};
return part;
});
if(query_parameters.length) {
query_parameters = JSON.stringify(query_parameters.length === 1?query_parameters[0]:query_parameters);
if(options.header_filter) {
options.query_parameters = query_parameters;
} else {
dataSet.q = query_parameters;
delete options.query_parameters;
}
} else {
delete options.query_parameters;
}
dataSet._match = 'starts_with';
if(options.columns) {
var order = data.order;
order.forEach(function (e,i) {
var order_col = e.column;
var order_by = options.columns[order_col].data;
var order_dir = e.dir == 'asc' ? '+' : '-';
dataSet._order_by = order_dir + (!order_by.includes('.')?'me.'+order_by:order_by);
});
}
return dataSet;
}
}
}, options);
}
return $(this).dataTable(settings);
};
})(jQuery);

View File

@ -123,3 +123,94 @@ jQuery.extend( jQuery.fn.dataTableExt.sort, {
});
}());
jQuery.fn.dataTable.ext.errMode = function(settings, note, message) {
console.warn(message);
};
(function($) {
$.fn.api = function(options) {
var settings = null;
if(options) {
settings = $.extend(true, {}, dataTablesDefaults, {
'deferRender': true,
"paging": true,
'serverSide': true,
'searching': true,
'pagingType': 'full',
'ajax': {
'type': 'GET',
'cache': true,
'dataSrc': 'data',
'beforeSend': function(xhr, settings) {
this._xhr = xhr;
if(options.embed) {
xhr.setRequestHeader('x-koha-embed', Array.isArray(options.embed)?options.embed.join(','):options.embed);
}
if(options.header_filter && options.query_parameters) {
xhr.setRequestHeader('x-koha-query', options.query_parameters);
delete options.query_parameters;
}
},
'dataFilter': function(data, type) {
var json = {data: JSON.parse(data)};
if(total = this._xhr.getResponseHeader('x-total-count')) {
json.recordsTotal = total;
json.recordsFiltered = total;
}
return JSON.stringify(json);
},
'data': function( data, settings ) {
var length = data.length;
var start = data.start;
var dataSet = {
_page: Math.floor(start/length) + 1,
_per_page: length
};
var filter = data.search.value;
var query_parameters = settings.aoColumns
.filter(function(col) {
return col.bSearchable && typeof col.data == 'string' && (data.columns[col.idx].search.value != '' || filter != '')
})
.map(function(col) {
var part = {};
part[!col.data.includes('.')?'me.'+col.data:col.data] = {like: (data.columns[col.idx].search.value != '' ? data.columns[col.idx].search.value : filter)+'%'};
return part;
});
if(query_parameters.length) {
query_parameters = JSON.stringify(query_parameters.length === 1?query_parameters[0]:query_parameters);
if(options.header_filter) {
options.query_parameters = query_parameters;
} else {
dataSet.q = query_parameters;
delete options.query_parameters;
}
} else {
delete options.query_parameters;
}
dataSet._match = 'starts_with';
if(options.columns) {
var order = data.order;
order.forEach(function (e,i) {
var order_col = e.column;
var order_by = options.columns[order_col].data;
var order_dir = e.dir == 'asc' ? '+' : '-';
dataSet._order_by = order_dir + (!order_by.includes('.')?'me.'+order_by:order_by);
});
}
return dataSet;
}
}
}, options);
}
return $(this).dataTable(settings);
};
})(jQuery);