Bug 35331: Add table actions hook to ILL table
[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 status_sub_or = [];
90             let subquery_and = [];
91
92             if (!patron && !status) return "";
93
94             if(patron){
95                 let patronquery = buildPatronSearchQuery(
96                     patron,
97                     {
98                         table_prefix: 'patron',
99                     }
100                 );
101                 subquery_and.push(patronquery);
102             }
103
104             if(status){
105                 const status_search_fields = "me.status,me.status_av";
106                 status_search_fields.split(',').forEach(function(attr){
107                     status_sub_or.push({
108                         [attr]:{"=": status }
109                     });
110                 });
111                 subquery_and.push(status_sub_or);
112             }
113
114             filters.push({"-and": subquery_and});
115
116             return filters;
117         },
118         "me.placed": function(){
119             if (Object.keys(additional_prefilters).length && borrower_prefilter) return "";
120             let placed_start = $('#illfilter_dateplaced_start').get(0)._flatpickr.selectedDates[0];
121             let placed_end = $('#illfilter_dateplaced_end').get(0)._flatpickr.selectedDates[0];
122             if (!placed_start && !placed_end) return "";
123             return {
124                 ...(placed_start && {">=": placed_start}),
125                 ...(placed_end && {"<=": placed_end})
126             }
127         },
128         "me.updated": function(){
129             if (Object.keys(additional_prefilters).length && borrower_prefilter) return "";
130             let updated_start = $('#illfilter_datemodified_start').get(0)._flatpickr.selectedDates[0];
131             let updated_end = $('#illfilter_datemodified_end').get(0)._flatpickr.selectedDates[0];
132             if (!updated_start && !updated_end) return "";
133             // set selected datetime hours and minutes to the end of the day
134             // to grab any request updated during that day
135             let updated_end_value = new Date(updated_end);
136             updated_end_value.setHours(updated_end_value.getHours()+23);
137             updated_end_value.setMinutes(updated_end_value.getMinutes()+59);
138             return {
139                 ...(updated_start && {">=": updated_start}),
140                 ...(updated_end && {"<=": updated_end_value})
141             }
142         },
143         "-and": function(){
144             let keyword = $("#illfilter_keyword").val();
145             if (!keyword) return "";
146
147             let filters = [];
148             let subquery_and = [];
149
150             const search_fields = "me.illrequest_id,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";
151             let sub_or = [];
152             search_fields.split(',').forEach(function(attr){
153                 sub_or.push({
154                         [attr]:{"like":"%" + keyword + "%"}
155                 });
156             });
157             subquery_and.push(sub_or);
158             filters.push({"-and": subquery_and});
159
160             let patronquery = buildPatronSearchQuery(
161                 keyword,
162                 {
163                     table_prefix: 'patron',
164                 }
165             );
166             filters.push(patronquery);
167
168             const extended_attributes = "title,type,author,article_title,pages,issue,volume,year";
169             let extended_sub_or = [];
170             subquery_and = [];
171             extended_sub_or.push({
172                 "extended_attributes.type": extended_attributes.split(','),
173                 "extended_attributes.value":{"like":"%" + keyword + "%"}
174             });
175             subquery_and.push(extended_sub_or);
176
177             filters.push({"-and": subquery_and});
178             return filters;
179         }
180     };
181
182     let table_id = "#ill-requests";
183
184     if (borrower_prefilter) {
185         table_id += "-patron-" + borrower_prefilter;
186     } else if ( batch_id_prefilter ){
187         table_id += "-batch-" + batch_id_prefilter;
188     }
189
190     var ill_requests_table = $(table_id).kohaTable({
191         "ajax": {
192             "url": '/api/v1/ill/requests'
193         },
194         "embed": [
195             '+strings',
196             'biblio',
197             'comments+count',
198             'extended_attributes',
199             'ill_batch',
200             'library',
201             'id_prefix',
202             'patron'
203         ],
204         "order": [[0, 'desc']],
205         "stateSave": true, // remember state on page reload
206         "columns": [
207             {
208                 "data": "ill_request_id",
209                 "searchable": true,
210                 "orderable": true,
211                 "render": function( data, type, row, meta ) {
212                     return '<a href="/cgi-bin/koha/ill/ill-requests.pl?' +
213                             'op=illview&amp;illrequest_id=' +
214                             encodeURIComponent(data) +
215                             '">' + escape_str(row.id_prefix) + escape_str(data) + '</a>';
216                 }
217             },
218             {
219                 "data": "batch.name", // batch
220                 "orderable": false,
221                 "render": function(data, type, row, meta) {
222                     return row.ill_batch ?
223                         '<a href="/cgi-bin/koha/ill/ill-requests.pl?batch_id=' +
224                         row.ill_batch.ill_batch_id +
225                         '">' +
226                         row.ill_batch.name +
227                         '</a>'
228                         : "";
229                 }
230             },
231             {
232                 "data": "", // author
233                 "orderable": false,
234                 "render": function(data, type, row, meta) {
235                     return display_extended_attribute(row, 'author');
236                 }
237             },
238             {
239                 "data": "", // title
240                 "orderable": false,
241                 "render": function(data, type, row, meta) {
242                     return display_extended_attribute(row, 'title');
243                 }
244             },
245             {
246                 "data": "", // article_title
247                 "orderable": false,
248                 "render": function(data, type, row, meta) {
249                     return display_extended_attribute(row, 'article_title');
250                 }
251             },
252             {
253                 "data": "", // issue
254                 "orderable": false,
255                 "render": function(data, type, row, meta) {
256                     return display_extended_attribute(row, 'issue');
257                 }
258             },
259             {
260                 "data": "", // volume
261                 "orderable": false,
262                 "render": function(data, type, row, meta) {
263                     return display_extended_attribute(row, 'volume');
264                 }
265             },
266             {
267                 "data": "",  // year
268                 "orderable": false,
269                 "render": function(data, type, row, meta) {
270                     return display_extended_attribute(row, 'year');
271                 }
272             },
273             {
274                 "data": "", // pages
275                 "orderable": false,
276                 "render": function(data, type, row, meta) {
277                     return display_extended_attribute(row, 'pages');
278                 }
279             },
280             {
281                 "data": "", // type
282                 "orderable": false,
283                 "render": function(data, type, row, meta) {
284                     return display_extended_attribute(row, 'type');
285                 }
286             },
287             {
288                 "data": "ill_backend_request_id",
289                 "orderable": true,
290                 "render": function(data, type, row, meta) {
291                     return escape_str(data);
292                 }
293             },
294             {
295                 "data": "patron.firstname:patron.surname:patron.cardnumber",
296                 "render": function(data, type, row, meta) {
297                     return (row.patron) ? $patron_to_html( row.patron, { display_cardnumber: true, url: true } ) : ''; }                    },
298             {
299                 "data": "biblio_id",
300                 "orderable": true,
301                 "render": function(data, type, row, meta) {
302                     if ( data === null ) {
303                         return "";
304                     }
305                     return $biblio_to_html(row.biblio, { biblio_id_only: 1, link: 1 });
306                 }
307             },
308             {
309                 "data": "library.name",
310                 "orderable": true,
311                 "render": function(data, type, row, meta) {
312                     return escape_str(data);
313                 }
314             },
315             {
316                 "data": "status",
317                 "orderable": true,
318                 "render": function(data, type, row, meta) {
319                     let status_label = row._strings.status_av ?
320                         row._strings.status_av.str ?
321                             row._strings.status_av.str :
322                             row._strings.status_av.code :
323                         row._strings.status.str
324                     return escape_str(status_label);
325                 }
326             },
327             {
328                 "data": "requested_date",
329                 "orderable": true,
330                 "render": function(data, type, row, meta) {
331                     return $date(data);
332                 }
333             },
334             {
335                 "data": "timestamp",
336                 "orderable": true,
337                 "render": function(data, type, row, meta) {
338                     return $date(data);
339                 }
340             },
341             {
342                 "data": "replied_date",
343                 "orderable": true,
344                 "render": function(data, type, row, meta) {
345                     return $date(data);
346                 }
347             },
348             {
349                 "data": "completed_date",
350                 "orderable": true,
351                 "render": function(data, type, row, meta) {
352                     return $date(data);
353                 }
354             },
355             {
356                 "data": "access_url",
357                 "orderable": true,
358                 "render": function(data, type, row, meta) {
359                     return '<a target="_blank" href="' + data + '">'
360                     + escape_str(data) + '</a>';
361                 }
362             },
363             {
364                 "data": "cost",
365                 "orderable": true,
366                 "render": function(data, type, row, meta) {
367                     return escape_str(data);
368                 }
369             },
370             {
371                 "data": "paid_price",
372                 "orderable": true,
373                 "render": function(data, type, row, meta) {
374                     return escape_str(data);
375                 }
376             },
377             {
378                 "data": "comments_count",
379                 "orderable": true,
380                 "searchable": false,
381                 "render": function(data, type, row, meta) {
382                     return escape_str(data);
383                 }
384             },
385             {
386                 "data": "opac_notes",
387                 "orderable": true,
388                 "render": function(data, type, row, meta) {
389                     return escape_str(data);
390                 }
391             },
392             {
393                 "data": "staff_notes",
394                 "orderable": true,
395                 "render": function(data, type, row, meta) {
396                     return escape_str(data);
397                 }
398             },
399             {
400                 "data": "ill_backend_id",
401                 "orderable": true,
402                 "render": function(data, type, row, meta) {
403                     return escape_str(data);
404                 }
405             },
406             {
407                 "data": "ill_request_id",
408                 "orderable": false,
409                 "searchable": false,
410                 "render": function( data, type, row, meta ) {
411                     return render_table_actions(data);
412                 }
413             }
414         ]
415     }, table_settings, null, additional_filters);
416
417     $("#illfilter_form").on('submit', filter);
418
419     function render_table_actions(data) {
420         let actions_string = "";
421         ill_table_actions.forEach((ill_table_action) => {
422             let link_data = ill_table_action.append_column_data_to_link
423                 ? encodeURIComponent(data)
424                 : "";
425             let link_text = ill_table_action.button_link_translatable_text
426                 ? eval(ill_table_action.button_link_translatable_text)
427                 : ill_table_action.button_link_text;
428             actions_string += `<a class="${ill_table_action.button_class}" href="${ill_table_action.button_link}${link_data}">${link_text}</a>`;
429         });
430         return actions_string;
431     }
432
433     function redrawTable() {
434         let table_dt = ill_requests_table.DataTable();
435         table_dt.draw();
436     }
437
438     function filter() {
439         redrawTable();
440         return false;
441     }
442
443     function clearSearch() {
444         let filters = [
445             "illfilter_backend",
446             "illfilter_branchname",
447             "illfilter_patron",
448             "illfilter_keyword",
449         ];
450         filters.forEach((filter) => {
451             $("#"+filter).val("");
452         });
453
454         //Clear flatpickr date filters
455         $('#illfilter_form > fieldset > ol > li:nth-child(4) > span > a').click();
456         $('#illfilter_form > fieldset > ol > li:nth-child(5) > span > a').click();
457         $('#illfilter_form > fieldset > ol > li:nth-child(6) > span > a').click();
458         $('#illfilter_form > fieldset > ol > li:nth-child(7) > span > a').click();
459
460         disableStatusFilter();
461
462         redrawTable();
463     }
464
465     function populateStatusFilter(backend) {
466         $.ajax({
467             type: "GET",
468             url: "/api/v1/ill/backends/"+backend,
469             headers: {
470                 'x-koha-embed': 'statuses+strings'
471             },
472             success: function(response){
473                 let statuses = response.statuses
474                 $('#illfilter_status').append(
475                     '<option value="">'+ill_all_statuses+'</option>'
476                 );
477                 statuses.sort((a, b) => a.str.localeCompare(b.str)).forEach(function(status) {
478                     $('#illfilter_status').append(
479                         '<option value="' + status.code  +
480                         '">' + status.str +  '</option>'
481                     );
482                 });
483             }
484         });
485     }
486
487     function populateBackendFilter() {
488         $.ajax({
489             type: "GET",
490             url: "/api/v1/ill/backends",
491             success: function(backends){
492                 backends.sort((a, b) => a.ill_backend_id.localeCompare(b.ill_backend_id)).forEach(function(backend) {
493                     $('#illfilter_backend').append(
494                         '<option value="' + backend.ill_backend_id  +
495                         '">' + backend.ill_backend_id +  '</option>'
496                     );
497                 });
498             }
499         });
500     }
501
502     function disableStatusFilter() {
503         $('#illfilter_status').children().remove();
504         $("#illfilter_status").attr('title', ill_manage_select_backend_first);
505         $('#illfilter_status').prop("disabled", true);
506     }
507
508     function enableStatusFilter() {
509         $('#illfilter_status').children().remove();
510         $("#illfilter_status").attr('title', '');
511         $('#illfilter_status').prop("disabled", false);
512     }
513
514     $('#illfilter_backend').change(function() {
515         var selected_backend = $('#illfilter_backend option:selected').val();
516         if (selected_backend && selected_backend.length > 0) {
517             populateStatusFilter(selected_backend);
518             enableStatusFilter();
519         } else {
520             disableStatusFilter();
521         }
522     });
523
524     disableStatusFilter();
525     populateBackendFilter();
526
527     // Clear all filters
528     $('#clear_search').click(function() {
529         clearSearch();
530     });
531
532 });