Bug 30719: ILL Batches
[koha.git] / koha-tmpl / intranet-tmpl / prog / js / ill-list-table.js
1 $(document).ready(function() {
2     // Display the modal containing request supplier metadata
3     $('#ill-request-display-log').on('click', function(e) {
4         e.preventDefault();
5         $('#requestLog').modal({show:true});
6     });
7
8     // Toggle request attributes in Illview
9     $('#toggle_requestattributes').on('click', function(e) {
10         e.preventDefault();
11         $('#requestattributes').toggleClass('content_hidden');
12     });
13
14     // Toggle new comment form in Illview
15     $('#toggle_addcomment').on('click', function(e) {
16         e.preventDefault();
17         $('#addcomment').toggleClass('content_hidden');
18     });
19
20     // Filter partner list
21     // Record the list of all options
22     var ill_partner_options = $('#partners > option');
23     $('#partner_filter').keyup(function() {
24         var needle = $('#partner_filter').val();
25         var regex = new RegExp(needle, 'i');
26         var filtered = [];
27         ill_partner_options.each(function() {
28             if (
29                 needle.length == 0 ||
30                 $(this).is(':selected') ||
31                 $(this).text().match(regex)
32             ) {
33                 filtered.push($(this));
34             }
35         });
36         $('#partners').empty().append(filtered);
37     });
38
39     // Display the modal containing request supplier metadata
40     $('#ill-request-display-metadata').on('click', function(e) {
41         e.preventDefault();
42         $('#dataPreview').modal({show:true});
43     });
44
45     function display_extended_attribute(row, type) {
46         var arr = $.grep(row.extended_attributes, ( x => x.type === type ));
47         if (arr.length > 0) {
48             return escape_str(arr[0].value);
49         }
50
51         return '';
52     }
53
54     // Possible prefilters: borrowernumber, batch_id
55     // see ill/ill-requests.pl and members/ill-requests.pl
56     let additional_prefilters = {};
57     if(prefilters){
58         let prefilters_array = prefilters.split("&");
59         prefilters_array.forEach((prefilter) => {
60             let prefilter_split = prefilter.split("=");
61             additional_prefilters[prefilter_split[0]] = prefilter_split[1]
62         });
63     }
64
65     let borrower_prefilter = additional_prefilters['borrowernumber'] || null;
66     let batch_id_prefilter = additional_prefilters['batch_id'] || null;
67
68     let additional_filters = {
69         "me.backend": function(){
70             let backend = $("#illfilter_backend").val();
71             if (!backend) return "";
72             return { "=": backend  }
73         },
74         "me.branchcode": function(){
75             let branchcode = $("#illfilter_branchname").val();
76             if (!branchcode) return "";
77             return { "=": branchcode }
78         },
79         "me.borrowernumber": function(){
80             return borrower_prefilter ? { "=": borrower_prefilter } : "";
81         },
82         "me.batch_id": function(){
83             return batch_id_prefilter ? { "=": batch_id_prefilter } : "";
84         },
85         "-or": function(){
86             let patron = $("#illfilter_patron").val();
87             let status = $("#illfilter_status").val();
88             let filters = [];
89             let patron_sub_or = [];
90             let status_sub_or = [];
91             let subquery_and = [];
92
93             if (!patron && !status) return "";
94
95             if(patron){
96                 const patron_search_fields = "me.borrowernumber,patron.cardnumber,patron.firstname,patron.surname";
97                 patron_search_fields.split(',').forEach(function(attr){
98                     let operator = "=";
99                     let patron_data = patron;
100                     if ( attr != "me.borrowernumber" && attr != "patron.cardnumber") {
101                         operator = "like";
102                         patron_data = "%" + patron + "%";
103                     }
104                     patron_sub_or.push({
105                         [attr]:{[operator]: patron_data }
106                     });
107                 });
108                 subquery_and.push(patron_sub_or);
109             }
110
111             if(status){
112                 const status_search_fields = "me.status,me.status_av";
113                 status_search_fields.split(',').forEach(function(attr){
114                     status_sub_or.push({
115                         [attr]:{"=": status }
116                     });
117                 });
118                 subquery_and.push(status_sub_or);
119             }
120
121             filters.push({"-and": subquery_and});
122
123             return filters;
124         },
125         "me.placed": function(){
126             if (Object.keys(additional_prefilters).length && borrower_prefilter) return "";
127             let placed_start = $('#illfilter_dateplaced_start').get(0)._flatpickr.selectedDates[0];
128             let placed_end = $('#illfilter_dateplaced_end').get(0)._flatpickr.selectedDates[0];
129             if (!placed_start && !placed_end) return "";
130             return {
131                 ...(placed_start && {">=": placed_start}),
132                 ...(placed_end && {"<=": placed_end})
133             }
134         },
135         "me.updated": function(){
136             if (Object.keys(additional_prefilters).length && borrower_prefilter) return "";
137             let updated_start = $('#illfilter_datemodified_start').get(0)._flatpickr.selectedDates[0];
138             let updated_end = $('#illfilter_datemodified_end').get(0)._flatpickr.selectedDates[0];
139             if (!updated_start && !updated_end) return "";
140             // set selected datetime hours and minutes to the end of the day
141             // to grab any request updated during that day
142             let updated_end_value = new Date(updated_end);
143             updated_end_value.setHours(updated_end_value.getHours()+23);
144             updated_end_value.setMinutes(updated_end_value.getMinutes()+59);
145             return {
146                 ...(updated_start && {">=": updated_start}),
147                 ...(updated_end && {"<=": updated_end_value})
148             }
149         },
150         "-and": function(){
151             let keyword = $("#illfilter_keyword").val();
152             if (!keyword) return "";
153
154             let filters = [];
155             let subquery_and = [];
156
157             const search_fields = "me.illrequest_id,me.borrowernumber,me.biblio_id,me.due_date,me.branchcode,library.name,me.status,me.status_alias,me.placed,me.replied,me.updated,me.completed,me.medium,me.accessurl,me.cost,me.price_paid,me.notesopac,me.notesstaff,me.orderid,me.backend,patron.firstname,patron.surname";
158             let sub_or = [];
159             search_fields.split(',').forEach(function(attr){
160                 sub_or.push({
161                         [attr]:{"like":"%" + keyword + "%"}
162                 });
163             });
164             subquery_and.push(sub_or);
165             filters.push({"-and": subquery_and});
166
167             const extended_attributes = "title,type,author,article_title,pages,issue,volume,year";
168             let extended_sub_or = [];
169             subquery_and = [];
170             extended_sub_or.push({
171                 "extended_attributes.type": extended_attributes.split(','),
172                 "extended_attributes.value":{"like":"%" + keyword + "%"}
173             });
174             subquery_and.push(extended_sub_or);
175
176             filters.push({"-and": subquery_and});
177             return filters;
178         }
179     };
180
181     let table_id = "#ill-requests";
182
183     if (borrower_prefilter) {
184         table_id += "-patron-" + borrower_prefilter;
185     } else if ( batch_id_prefilter ){
186         table_id += "-batch-" + batch_id_prefilter;
187     }
188
189     var ill_requests_table = $(table_id).kohaTable({
190         "ajax": {
191             "url": '/api/v1/ill/requests'
192         },
193         "embed": [
194             '+strings',
195             'biblio',
196             'comments+count',
197             'extended_attributes',
198             'batch',
199             'library',
200             'id_prefix',
201             'patron'
202         ],
203         "order": [[0, 'desc']],
204         "stateSave": true, // remember state on page reload
205         "columns": [
206             {
207                 "data": "ill_request_id",
208                 "searchable": true,
209                 "orderable": true,
210                 "render": function( data, type, row, meta ) {
211                     return '<a href="/cgi-bin/koha/ill/ill-requests.pl?' +
212                             'method=illview&amp;illrequest_id=' +
213                             encodeURIComponent(data) +
214                             '">' + escape_str(row.id_prefix) + escape_str(data) + '</a>';
215                 }
216             },
217             {
218                 "data": "batch.name", // batch
219                 "orderable": false,
220                 "render": function(data, type, row, meta) {
221                     return row.batch ?
222                         '<a href="/cgi-bin/koha/ill/ill-requests.pl?batch_id=' +
223                         row.batch_id +
224                         '">' +
225                         row.batch.name +
226                         '</a>'
227                         : "";
228                 }
229             },
230             {
231                 "data": "", // author
232                 "orderable": false,
233                 "render": function(data, type, row, meta) {
234                     return display_extended_attribute(row, 'author');
235                 }
236             },
237             {
238                 "data": "", // title
239                 "orderable": false,
240                 "render": function(data, type, row, meta) {
241                     return display_extended_attribute(row, 'title');
242                 }
243             },
244             {
245                 "data": "", // article_title
246                 "orderable": false,
247                 "render": function(data, type, row, meta) {
248                     return display_extended_attribute(row, 'article_title');
249                 }
250             },
251             {
252                 "data": "", // issue
253                 "orderable": false,
254                 "render": function(data, type, row, meta) {
255                     return display_extended_attribute(row, 'issue');
256                 }
257             },
258             {
259                 "data": "", // volume
260                 "orderable": false,
261                 "render": function(data, type, row, meta) {
262                     return display_extended_attribute(row, 'volume');
263                 }
264             },
265             {
266                 "data": "",  // year
267                 "orderable": false,
268                 "render": function(data, type, row, meta) {
269                     return display_extended_attribute(row, 'year');
270                 }
271             },
272             {
273                 "data": "", // pages
274                 "orderable": false,
275                 "render": function(data, type, row, meta) {
276                     return display_extended_attribute(row, 'pages');
277                 }
278             },
279             {
280                 "data": "", // type
281                 "orderable": false,
282                 "render": function(data, type, row, meta) {
283                     return display_extended_attribute(row, 'type');
284                 }
285             },
286             {
287                 "data": "ill_backend_request_id",
288                 "orderable": true,
289                 "render": function(data, type, row, meta) {
290                     return escape_str(data);
291                 }
292             },
293             {
294                 "data": "patron.firstname:patron.surname:patron.cardnumber",
295                 "render": function(data, type, row, meta) {
296                     return (row.patron) ? $patron_to_html( row.patron, { display_cardnumber: true, url: true } ) : ''; }                    },
297             {
298                 "data": "biblio_id",
299                 "orderable": true,
300                 "render": function(data, type, row, meta) {
301                     if ( data === null ) {
302                         return "";
303                     }
304                     return $biblio_to_html(row.biblio, { biblio_id_only: 1, link: 1 });
305                 }
306             },
307             {
308                 "data": "library.name",
309                 "orderable": true,
310                 "render": function(data, type, row, meta) {
311                     return escape_str(data);
312                 }
313             },
314             {
315                 "data": "status",
316                 "orderable": true,
317                 "render": function(data, type, row, meta) {
318                     let status_label = row._strings.status_av ?
319                         row._strings.status_av.str ?
320                             row._strings.status_av.str :
321                             row._strings.status_av.code :
322                         row._strings.status.str
323                     return escape_str(status_label);
324                 }
325             },
326             {
327                 "data": "requested_date",
328                 "orderable": true,
329                 "render": function(data, type, row, meta) {
330                     return $date(data);
331                 }
332             },
333             {
334                 "data": "timestamp",
335                 "orderable": true,
336                 "render": function(data, type, row, meta) {
337                     return $date(data);
338                 }
339             },
340             {
341                 "data": "replied_date",
342                 "orderable": true,
343                 "render": function(data, type, row, meta) {
344                     return $date(data);
345                 }
346             },
347             {
348                 "data": "completed_date",
349                 "orderable": true,
350                 "render": function(data, type, row, meta) {
351                     return $date(data);
352                 }
353             },
354             {
355                 "data": "access_url",
356                 "orderable": true,
357                 "render": function(data, type, row, meta) {
358                     return '<a target="_blank" href="' + data + '">'
359                     + escape_str(data) + '</a>';
360                 }
361             },
362             {
363                 "data": "cost",
364                 "orderable": true,
365                 "render": function(data, type, row, meta) {
366                     return escape_str(data);
367                 }
368             },
369             {
370                 "data": "paid_price",
371                 "orderable": true,
372                 "render": function(data, type, row, meta) {
373                     return escape_str(data);
374                 }
375             },
376             {
377                 "data": "comments_count",
378                 "orderable": true,
379                 "searchable": false,
380                 "render": function(data, type, row, meta) {
381                     return escape_str(data);
382                 }
383             },
384             {
385                 "data": "opac_notes",
386                 "orderable": true,
387                 "render": function(data, type, row, meta) {
388                     return escape_str(data);
389                 }
390             },
391             {
392                 "data": "staff_notes",
393                 "orderable": true,
394                 "render": function(data, type, row, meta) {
395                     return escape_str(data);
396                 }
397             },
398             {
399                 "data": "ill_backend_id",
400                 "orderable": true,
401                 "render": function(data, type, row, meta) {
402                     return escape_str(data);
403                 }
404             },
405             {
406                 "data": "ill_request_id",
407                 "orderable": false,
408                 "searchable": false,
409                 "render": function( data, type, row, meta ) {
410                     return '<a class="btn btn-default btn-sm" ' +
411                             'href="/cgi-bin/koha/ill/ill-requests.pl?' +
412                             'method=illview&amp;illrequest_id=' +
413                             encodeURIComponent(data) +
414                             '">' + ill_manage + '</a>';
415                 }
416             }
417         ]
418     }, table_settings, null, additional_filters);
419
420     $("#illfilter_form").on('submit', filter);
421
422     function redrawTable() {
423         let table_dt = ill_requests_table.DataTable();
424         table_dt.draw();
425     }
426
427     function filter() {
428         redrawTable();
429         return false;
430     }
431
432     function clearSearch() {
433         let filters = [
434             "illfilter_backend",
435             "illfilter_branchname",
436             "illfilter_patron",
437             "illfilter_keyword",
438         ];
439         filters.forEach((filter) => {
440             $("#"+filter).val("");
441         });
442
443         //Clear flatpickr date filters
444         $('#illfilter_form > fieldset > ol > li:nth-child(4) > span > a').click();
445         $('#illfilter_form > fieldset > ol > li:nth-child(5) > span > a').click();
446         $('#illfilter_form > fieldset > ol > li:nth-child(6) > span > a').click();
447         $('#illfilter_form > fieldset > ol > li:nth-child(7) > span > a').click();
448
449         disableStatusFilter();
450
451         redrawTable();
452     }
453
454     function populateStatusFilter(backend) {
455         $.ajax({
456             type: "GET",
457             url: "/api/v1/ill/backends/"+backend,
458             headers: {
459                 'x-koha-embed': 'statuses+strings'
460             },
461             success: function(response){
462                 let statuses = response.statuses
463                 $('#illfilter_status').append(
464                     '<option value="">'+ill_all_statuses+'</option>'
465                 );
466                 statuses.sort((a, b) => a.str.localeCompare(b.str)).forEach(function(status) {
467                     $('#illfilter_status').append(
468                         '<option value="' + status.code  +
469                         '">' + status.str +  '</option>'
470                     );
471                 });
472             }
473         });
474     }
475
476     function populateBackendFilter() {
477         $.ajax({
478             type: "GET",
479             url: "/api/v1/ill/backends",
480             success: function(backends){
481                 backends.sort((a, b) => a.ill_backend_id.localeCompare(b.ill_backend_id)).forEach(function(backend) {
482                     $('#illfilter_backend').append(
483                         '<option value="' + backend.ill_backend_id  +
484                         '">' + backend.ill_backend_id +  '</option>'
485                     );
486                 });
487             }
488         });
489     }
490
491     function disableStatusFilter() {
492         $('#illfilter_status').children().remove();
493         $("#illfilter_status").attr('title', ill_manage_select_backend_first);
494         $('#illfilter_status').prop("disabled", true);
495     }
496
497     function enableStatusFilter() {
498         $('#illfilter_status').children().remove();
499         $("#illfilter_status").attr('title', '');
500         $('#illfilter_status').prop("disabled", false);
501     }
502
503     $('#illfilter_backend').change(function() {
504         var selected_backend = $('#illfilter_backend option:selected').val();
505         if (selected_backend && selected_backend.length > 0) {
506             populateStatusFilter(selected_backend);
507             enableStatusFilter();
508         } else {
509             disableStatusFilter();
510         }
511     });
512
513     disableStatusFilter();
514     populateBackendFilter();
515
516     // Clear all filters
517     $('#clear_search').click(function() {
518         clearSearch();
519     });
520
521 });