1 $(document).ready(function() {
3 // Illview Datatable setup
7 // Filters that are active
8 var activeFilters = {};
11 var prefilters = $('table#ill-requests').data('prefilters');
13 // Fields we need to expand (flatten)
21 // This is auto populated
27 prep: function(tableData, oData) {
29 tableData.forEach(function(row) {
31 if (row.status_alias) {
32 resolvedName = row.status_alias.lib;
34 resolvedName = getStatusName(
35 oData[0].capabilities[row.status].name
38 uniques[resolvedName] = 1
40 Object.keys(uniques).sort().forEach(function(unique) {
41 $('#illfilter_status').append(
42 '<option value="' + unique +
43 '">' + unique + '</option>'
47 listener: function() {
49 $('#illfilter_status').change(function() {
50 var sel = $('#illfilter_status option:selected').val();
51 if (sel && sel.length > 0) {
52 activeFilters[me] = function() {
53 table.api().column(13).search(sel);
56 if (activeFilters.hasOwnProperty(me)) {
57 delete activeFilters[me];
63 $('#illfilter_status').val('');
67 prep: function(tableData, oData) {
69 tableData.forEach(function(row) {
70 uniques[row.library_branchname] = 1
72 Object.keys(uniques).sort().forEach(function(unique) {
73 $('#illfilter_branchname').append(
74 '<option value="' + unique +
75 '">' + unique + '</option>'
79 listener: function() {
80 var me = 'pickupBranch';
81 $('#illfilter_branchname').change(function() {
82 var sel = $('#illfilter_branchname option:selected').val();
83 if (sel && sel.length > 0) {
84 activeFilters[me] = function() {
85 table.api().column(12).search(sel);
88 if (activeFilters.hasOwnProperty(me)) {
89 delete activeFilters[me];
95 $('#illfilter_branchname').val('');
99 listener: function() {
101 $('#illfilter_patron').change(function() {
102 var val = $('#illfilter_patron').val();
103 if (val && val.length > 0) {
104 activeFilters[me] = function() {
105 table.api().column(10).search(val);
108 if (activeFilters.hasOwnProperty(me)) {
109 delete activeFilters[me];
115 $('#illfilter_patron').val('');
120 $('#illfilter_datemodified_start, #illfilter_datemodified_end').val('');
125 $('#illfilter_dateplaced_start, #illfilter_dateplaced_end').val('');
130 // Expand any fields we're expanding
131 var expandExpand = function(row) {
132 expand.forEach(function(thisExpand) {
133 if (row.hasOwnProperty(thisExpand)) {
134 if (!expanded.hasOwnProperty(thisExpand)) {
135 expanded[thisExpand] = [];
137 var expandObj = row[thisExpand];
138 Object.keys(expandObj).forEach(
139 function(thisExpandCol) {
140 var expColName = thisExpand + '_' + thisExpandCol.replace(/\s/g,'_');
141 // Keep a list of fields that have been expanded
142 // so we can create toggle links for them
143 if (expanded[thisExpand].indexOf(expColName) == -1) {
144 expanded[thisExpand].push(expColName);
146 expandObj[expColName] =
147 expandObj[thisExpandCol];
148 delete expandObj[thisExpandCol];
151 $.extend(true, row, expandObj);
152 delete row[thisExpand];
157 // Strip the expand prefix if it exists, we do this for display
158 var stripPrefix = function(value) {
159 expand.forEach(function(thisExpand) {
160 var regex = new RegExp(thisExpand + '_', 'g');
161 value = value.replace(regex, '');
166 // Our 'render' function for borrowerlink
167 var createPatronLink = function(data, type, row) {
168 var patronLink = '<a title="' + ill_borrower_details + '" ' +
169 'href="/cgi-bin/koha/members/moremember.pl?' +
170 'borrowernumber='+row.borrowernumber+'">';
171 if ( row.patron_firstname ) {
172 patronLink = patronLink + row.patron_firstname + ' ';
174 patronLink = patronLink + row.patron_surname +
175 ' (' + row.patron_cardnumber + ')' + '</a>';
179 // Our 'render' function for biblio_id
180 var createBiblioLink = function(data, type, row) {
181 return (row.biblio_id) ?
182 '<a title="' + ill_biblio_details + '" ' +
183 'href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' +
184 row.biblio_id + '">' +
189 // Our 'render' function for title
190 var createTitle = function(data, type, row) {
192 row.hasOwnProperty('metadata_container_title') &&
193 row.metadata_container_title
194 ) ? row.metadata_container_title : row.metadata_title;
197 // Render function for request ID
198 var createRequestId = function(data, type, row) {
199 return row.id_prefix + row.illrequest_id;
202 // Render function for type
203 var createType = function(data, type, row) {
204 if (!row.hasOwnProperty('metadata_Type') || !row.metadata_Type) {
205 if (row.hasOwnProperty('medium') && row.medium) {
206 row.metadata_Type = row.medium;
208 row.metadata_Type = null;
211 return row.metadata_Type;
214 // Render function for request status
215 var createStatus = function(data, type, row, meta) {
216 if (row.status_alias) {
217 return row.status_alias.lib
218 ? row.status_alias.lib
219 : row.status_alias.authorised_value;
221 var origData = meta.settings.oInit.originalData;
222 if (origData.length > 0) {
223 var status_name = meta.settings.oInit.originalData[0].capabilities[
226 return getStatusName(status_name, row);
233 var getStatusName = function(origName, row) {
236 return ill_statuses.new;
238 return ill_statuses.req;
239 case "Requested from partners":
240 var statStr = ill_statuses.genreq;
242 row.hasOwnProperty('requested_partners') &&
243 row.requested_partners &&
244 row.requested_partners.length > 0
246 statStr += ' (' + row.requested_partners + ')';
249 case "Request reverted":
250 return ill_statuses.rev;
251 case "Queued request":
252 return ill_statuses.que;
253 case "Cancellation requested":
254 return ill_statuses.canc;
256 return ill_statuses.comp;
257 case "Delete request":
258 return ill_statuses.del;
264 // Render function for creating a row's action link
265 var createActionLink = function(data, type, row) {
266 return '<a class="btn btn-default btn-sm" ' +
267 'href="/cgi-bin/koha/ill/ill-requests.pl?' +
268 'method=illview&illrequest_id=' +
270 '">' + ill_manage + '</a>';
273 // Columns that require special treatment
276 func: createActionLink,
280 func: createRequestId
286 name: ill_columns.biblio_id,
287 func: createBiblioLink,
297 name: ill_columns.updated
301 func: createPatronLink
305 // Display the modal containing request supplier metadata
306 $('#ill-request-display-log').on('click', function(e) {
308 $('#requestLog').modal({show:true});
311 // Toggle request attributes in Illview
312 $('#toggle_requestattributes').on('click', function(e) {
314 $('#requestattributes').toggleClass('content_hidden');
317 // Toggle new comment form in Illview
318 $('#toggle_addcomment').on('click', function(e) {
320 $('#addcomment').toggleClass('content_hidden');
323 // Filter partner list
324 $('#partner_filter').keyup(function() {
325 var needle = $('#partner_filter').val();
326 $('#partners > option').each(function() {
327 var regex = new RegExp(needle, 'i');
329 needle.length == 0 ||
330 $(this).is(':selected') ||
331 $(this).text().match(regex)
340 // Display the modal containing request supplier metadata
341 $('#ill-request-display-metadata').on('click', function(e) {
343 $('#dataPreview').modal({show:true});
346 // Allow us to chain Datatable render helpers together, so we
347 // can use our custom functions and render.text(), which
348 // provides us with data sanitization
349 $.fn.dataTable.render.multi = function(renderArray) {
350 return function(d, type, row, meta) {
351 for(var r = 0; r < renderArray.length; r++) {
352 var toCall = renderArray[r].hasOwnProperty('display') ?
353 renderArray[r].display :
355 d = toCall(d, type, row, meta);
361 // Get our data from the API and process it prior to passing
363 var filterParam = prefilters ? '&' + prefilters : '';
365 '/api/v1/illrequests?embed=metadata,patron,capabilities,library,status_alias,comments,requested_partners'
368 var data = JSON.parse(ajax.responseText);
369 // Make a copy, we'll be removing columns next and need
370 // to be able to refer to data that has been removed
371 var dataCopy = $.extend(true, [], data);
372 // Expand columns that need it and create an array
373 // of all column names
374 $.each(dataCopy, function(k, row) {
378 // Assemble an array of column definitions for passing
381 columns_settings.forEach(function(thisCol) {
382 var colName = thisCol.columnname;
383 // Create the base column object
384 var colObj = $.extend({}, thisCol);
385 colObj.name = colName;
386 colObj.className = colName;
387 colObj.defaultContent = '';
389 // We may need to process the data going in this
390 // column, so do it if necessary
392 specialCols.hasOwnProperty(colName) &&
393 specialCols[colName].hasOwnProperty('func')
396 specialCols[colName].func
398 if (!specialCols[colName].skipSanitize) {
400 $.fn.dataTable.render.text()
404 colObj.render = $.fn.dataTable.render.multi(
408 colObj.data = colName;
409 colObj.render = $.fn.dataTable.render.text()
411 // Make sure properties that aren't present in the API
412 // response are populated with null to avoid Datatables
413 // choking on their absence
414 dataCopy.forEach(function(thisData) {
415 if (!thisData.hasOwnProperty(colName)) {
416 thisData[colName] = null;
419 colData.push(colObj);
422 // Initialise the datatable
423 table = KohaTable("ill-requests", {
425 { // Last column shouldn't be sortable or searchable
426 'aTargets': [ 'actions' ],
430 { // When sorting 'placed', we want to use the
431 // unformatted column
432 'aTargets': [ 'placed_formatted'],
435 { // When sorting 'updated', we want to use the
436 // unformatted column
437 'aTargets': [ 'updated_formatted'],
440 { // When sorting 'completed', we want to use the
441 // unformatted column
442 'aTargets': [ 'completed_formatted'],
446 'aaSorting': [[ 16, 'desc' ]], // Default sort, updated descending
447 'processing': true, // Display a message when manipulating
448 'sPaginationType': "full_numbers", // Pagination display
449 'deferRender': true, // Improve performance on big datasets
452 'originalData': data, // Enable render functions to access
454 'initComplete': function() {
456 // Prepare any filter elements that need it
457 for (var el in filterable) {
458 if (filterable.hasOwnProperty(el)) {
459 if (filterable[el].hasOwnProperty('prep')) {
460 filterable[el].prep(dataCopy, data);
462 if (filterable[el].hasOwnProperty('listener')) {
463 filterable[el].listener();
469 }, columns_settings);
471 // Custom date range filtering
472 $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
473 var placedStart = $('#illfilter_dateplaced_start').datepicker('getDate');
474 var placedEnd = $('#illfilter_dateplaced_end').datepicker('getDate');
475 var modifiedStart = $('#illfilter_datemodified_start').datepicker('getDate');
476 var modifiedEnd = $('#illfilter_datemodified_end').datepicker('getDate');
477 var rowPlaced = data[14] ? new Date(data[14]) : null;
478 var rowModified = data[16] ? new Date(data[16]) : null;
479 var placedPassed = true;
480 var modifiedPassed = true;
481 if (placedStart && rowPlaced && rowPlaced < placedStart) {
484 if (placedEnd && rowPlaced && rowPlaced > placedEnd) {
485 placedPassed = false;
487 if (modifiedStart && rowModified && rowModified < modifiedStart) {
488 modifiedPassed = false
490 if (modifiedEnd && rowModified && rowModified > modifiedEnd) {
491 modifiedPassed = false;
494 return placedPassed && modifiedPassed;
501 var clearSearch = function() {
502 table.api().search('').columns().search('');
504 for (var filter in filterable) {
506 filterable.hasOwnProperty(filter) &&
507 filterable[filter].hasOwnProperty('clear')
509 filterable[filter].clear();
515 // Apply any search filters, or clear any previous
517 $('#illfilter_form').submit(function(event) {
518 event.preventDefault();
519 table.api().search('').columns().search('');
520 for (var active in activeFilters) {
521 if (activeFilters.hasOwnProperty(active)) {
522 activeFilters[active]();
529 $('#clear_search').click(function() {