Lines 2-496
Link Here
|
2 |
[% USE Branches %] |
2 |
[% USE Branches %] |
3 |
[% USE Koha %] |
3 |
[% USE Koha %] |
4 |
[% USE KohaDates %] |
4 |
[% USE KohaDates %] |
5 |
|
5 |
[% SET footerjs = 1 %] |
6 |
[% INCLUDE 'doc-head-open.inc' %] |
6 |
[% INCLUDE 'doc-head-open.inc' %] |
7 |
<title>Koha › ILL requests ›</title> |
7 |
<title>Koha › ILL requests</title> |
8 |
[% INCLUDE 'doc-head-close.inc' %] |
8 |
[% INCLUDE 'doc-head-close.inc' %] |
9 |
[% Asset.js("lib/jquery/plugins/jquery.checkboxes.min.js") %] |
|
|
10 |
[% Asset.css("css/datatables.css") %] |
9 |
[% Asset.css("css/datatables.css") %] |
11 |
[% INCLUDE 'datatables.inc' %] |
|
|
12 |
[% INCLUDE 'calendar.inc' %] |
13 |
<script type="text/javascript"> |
14 |
//<![CDATA[ |
15 |
$(document).ready(function() { |
16 |
|
17 |
// Illview Datatable setup |
18 |
|
19 |
var table; |
20 |
|
21 |
// Filters that are active |
22 |
var activeFilters = {}; |
23 |
|
24 |
// Fields we don't want to display |
25 |
var ignore = [ |
26 |
'accessurl', |
27 |
'backend', |
28 |
'branchcode', |
29 |
'completed', |
30 |
'capabilities', |
31 |
'cost', |
32 |
'medium', |
33 |
'notesopac', |
34 |
'notesstaff', |
35 |
'replied' |
36 |
]; |
37 |
|
38 |
// Fields we need to expand (flatten) |
39 |
var expand = [ |
40 |
'metadata', |
41 |
'patron' |
42 |
]; |
43 |
|
44 |
// Expanded fields |
45 |
// This is auto populated |
46 |
var expanded = {}; |
47 |
|
48 |
// The core fields that should be displayed first |
49 |
var core = [ |
50 |
'metadata_Author', |
51 |
'metadata_Title', |
52 |
'borrowername', |
53 |
'patron_cardnumber', |
54 |
'biblio_id', |
55 |
'library', |
56 |
'status', |
57 |
'placed', |
58 |
'placed_formatted', |
59 |
'updated', |
60 |
'updated_formatted', |
61 |
'illrequest_id', |
62 |
'action' |
63 |
]; |
64 |
|
65 |
// Filterable columns |
66 |
var filterable = { |
67 |
status: { |
68 |
prep: function(tableData, oData) { |
69 |
var uniques = {}; |
70 |
tableData.forEach(function(row) { |
71 |
var resolvedName = getStatusName( |
72 |
oData[0].capabilities[row.status].name |
73 |
); |
74 |
uniques[resolvedName] = 1 |
75 |
}); |
76 |
Object.keys(uniques).sort().forEach(function(unique) { |
77 |
$('#illfilter_status').append( |
78 |
'<option value="' + unique + |
79 |
'">' + unique + '</option>' |
80 |
); |
81 |
}); |
82 |
}, |
83 |
listener: function() { |
84 |
var me = 'status'; |
85 |
$('#illfilter_status').change(function() { |
86 |
var sel = $('#illfilter_status option:selected').val(); |
87 |
if (sel && sel.length > 0) { |
88 |
activeFilters[me] = function() { |
89 |
table.column(6).search(sel); |
90 |
} |
91 |
} else { |
92 |
if (activeFilters.hasOwnProperty(me)) { |
93 |
delete activeFilters[me]; |
94 |
} |
95 |
} |
96 |
}); |
97 |
}, |
98 |
clear: function() { |
99 |
$('#illfilter_status').val(''); |
100 |
} |
101 |
}, |
102 |
pickupBranch: { |
103 |
prep: function(tableData, oData) { |
104 |
var uniques = {}; |
105 |
tableData.forEach(function(row) { |
106 |
uniques[row.library.branchname] = 1 |
107 |
}); |
108 |
Object.keys(uniques).sort().forEach(function(unique) { |
109 |
$('#illfilter_branchname').append( |
110 |
'<option value="' + unique + |
111 |
'">' + unique + '</option>' |
112 |
); |
113 |
}); |
114 |
}, |
115 |
listener: function() { |
116 |
var me = 'pickupBranch'; |
117 |
$('#illfilter_branchname').change(function() { |
118 |
var sel = $('#illfilter_branchname option:selected').val(); |
119 |
if (sel && sel.length > 0) { |
120 |
activeFilters[me] = function() { |
121 |
table.column(5).search(sel); |
122 |
} |
123 |
} else { |
124 |
if (activeFilters.hasOwnProperty(me)) { |
125 |
delete activeFilters[me]; |
126 |
} |
127 |
} |
128 |
}); |
129 |
}, |
130 |
clear: function() { |
131 |
$('#illfilter_branchname').val(''); |
132 |
} |
133 |
}, |
134 |
barcode: { |
135 |
listener: function() { |
136 |
var me = 'barcode'; |
137 |
$('#illfilter_barcode').change(function() { |
138 |
var val = $('#illfilter_barcode').val(); |
139 |
if (val && val.length > 0) { |
140 |
activeFilters[me] = function() { |
141 |
table.column(3).search(val); |
142 |
} |
143 |
} else { |
144 |
if (activeFilters.hasOwnProperty(me)) { |
145 |
delete activeFilters[me]; |
146 |
} |
147 |
} |
148 |
}); |
149 |
}, |
150 |
clear: function() { |
151 |
$('#illfilter_barcode').val(''); |
152 |
} |
153 |
}, |
154 |
dateModified: { |
155 |
clear: function() { |
156 |
$('#illfilter_datemodified_start, #illfilter_datemodified_end').val(''); |
157 |
} |
158 |
}, |
159 |
datePlaced: { |
160 |
clear: function() { |
161 |
$('#illfilter_dateplaced_start, #illfilter_dateplaced_end').val(''); |
162 |
} |
163 |
} |
164 |
}; |
165 |
|
166 |
// Remove any fields we're ignoring |
167 |
var removeIgnore = function(dataObj) { |
168 |
dataObj.forEach(function(thisRow) { |
169 |
ignore.forEach(function(thisIgnore) { |
170 |
if (thisRow.hasOwnProperty(thisIgnore)) { |
171 |
delete thisRow[thisIgnore]; |
172 |
} |
173 |
}); |
174 |
}); |
175 |
}; |
176 |
|
177 |
// Expand any fields we're expanding |
178 |
var expandExpand = function(row) { |
179 |
expand.forEach(function(thisExpand) { |
180 |
if (row.hasOwnProperty(thisExpand)) { |
181 |
if (!expanded.hasOwnProperty(thisExpand)) { |
182 |
expanded[thisExpand] = []; |
183 |
} |
184 |
var expandObj = row[thisExpand]; |
185 |
Object.keys(expandObj).forEach( |
186 |
function(thisExpandCol) { |
187 |
var expColName = thisExpand + '_' + thisExpandCol; |
188 |
// Keep a list of fields that have been expanded |
189 |
// so we can create toggle links for them |
190 |
if (expanded[thisExpand].indexOf(expColName) == -1) { |
191 |
expanded[thisExpand].push(expColName); |
192 |
} |
193 |
expandObj[expColName] = |
194 |
expandObj[thisExpandCol]; |
195 |
delete expandObj[thisExpandCol]; |
196 |
} |
197 |
); |
198 |
$.extend(true, row, expandObj); |
199 |
delete row[thisExpand]; |
200 |
} |
201 |
}); |
202 |
}; |
203 |
|
204 |
// Build a de-duped list of all column names |
205 |
var allCols = {}; |
206 |
core.map(function(thisCore) { |
207 |
allCols[thisCore] = 1; |
208 |
}); |
209 |
|
210 |
// Strip the expand prefix if it exists, we do this for display |
211 |
var stripPrefix = function(value) { |
212 |
expand.forEach(function(thisExpand) { |
213 |
var regex = new RegExp(thisExpand + '_', 'g'); |
214 |
value = value.replace(regex, ''); |
215 |
}); |
216 |
return value; |
217 |
}; |
218 |
|
219 |
// Our 'render' function for borrowerlink |
220 |
var createPatronLink = function(data, type, row) { |
221 |
return '<a title="' + _("View borrower details") + '" ' + |
222 |
'href="/cgi-bin/koha/members/moremember.pl?' + |
223 |
'borrowernumber='+row.borrowernumber+'">' + |
224 |
row.patron_firstname + ' ' + row.patron_surname + |
225 |
'</a>'; |
226 |
}; |
227 |
|
228 |
// Our 'render' function for the library name |
229 |
var createLibrary = function(data, type, row) { |
230 |
return row.library.branchname; |
231 |
}; |
232 |
|
233 |
// Render function for request ID |
234 |
var createRequestId = function(data, type, row) { |
235 |
return row.id_prefix + row.illrequest_id; |
236 |
}; |
237 |
|
238 |
// Render function for request status |
239 |
var createStatus = function(data, type, row, meta) { |
240 |
var origData = meta.settings.oInit.originalData; |
241 |
if (origData.length > 0) { |
242 |
var status_name = meta.settings.oInit.originalData[0].capabilities[ |
243 |
row.status |
244 |
].name; |
245 |
return getStatusName(status_name); |
246 |
} else { |
247 |
return ''; |
248 |
} |
249 |
}; |
250 |
|
251 |
var getStatusName = function(origName) { |
252 |
switch( origName ) { |
253 |
case "New request": |
254 |
return _("New request"); |
255 |
case "Requested": |
256 |
return _("Requested"); |
257 |
case "Requested from partners": |
258 |
return _("Requested from partners"); |
259 |
case "Request reverted": |
260 |
return _("Request reverted"); |
261 |
case "Queued request": |
262 |
return _("Queued request"); |
263 |
case "Cancellation requested": |
264 |
return _("Cancellation requested"); |
265 |
case "Completed": |
266 |
return _("Completed"); |
267 |
case "Delete request": |
268 |
return _("Delete request"); |
269 |
default: |
270 |
return origName; |
271 |
} |
272 |
}; |
273 |
|
274 |
// Render function for creating a row's action link |
275 |
var createActionLink = function(data, type, row) { |
276 |
return '<a class="btn btn-default btn-sm" ' + |
277 |
'href="/cgi-bin/koha/ill/ill-requests.pl?' + |
278 |
'method=illview&illrequest_id=' + |
279 |
row.illrequest_id + |
280 |
'">' + _("Manage request") + '</a>'; |
281 |
}; |
282 |
|
283 |
// Columns that require special treatment |
284 |
var specialCols = { |
285 |
action: { |
286 |
name: '', |
287 |
func: createActionLink |
288 |
}, |
289 |
borrowername: { |
290 |
name: _("Patron"), |
291 |
func: createPatronLink |
292 |
}, |
293 |
illrequest_id: { |
294 |
name: _("Request number"), |
295 |
func: createRequestId |
296 |
}, |
297 |
status: { |
298 |
name: _("Status"), |
299 |
func: createStatus |
300 |
}, |
301 |
biblio_id: { |
302 |
name: _("Biblio ID") |
303 |
}, |
304 |
library: { |
305 |
name: _("Library"), |
306 |
func: createLibrary |
307 |
}, |
308 |
updated: { |
309 |
name: _("Updated on"), |
310 |
}, |
311 |
patron_cardnumber: { |
312 |
name: _("Patron barcode") |
313 |
} |
314 |
}; |
315 |
|
316 |
// Toggle request attributes in Illview |
317 |
$('#toggle_requestattributes').on('click', function(e) { |
318 |
e.preventDefault(); |
319 |
$('#requestattributes').toggleClass('content_hidden'); |
320 |
}); |
321 |
|
322 |
// Filter partner list |
323 |
$('#partner_filter').keyup(function() { |
324 |
var needle = $('#partner_filter').val(); |
325 |
$('#partners > option').each(function() { |
326 |
var regex = new RegExp(needle, 'i'); |
327 |
if ( |
328 |
needle.length == 0 || |
329 |
$(this).is(':selected') || |
330 |
$(this).text().match(regex) |
331 |
) { |
332 |
$(this).show(); |
333 |
} else { |
334 |
$(this).hide(); |
335 |
} |
336 |
}); |
337 |
}); |
338 |
|
339 |
// Get our data from the API and process it prior to passing |
340 |
// it to datatables |
341 |
var ajax = $.ajax( |
342 |
'/api/v1/illrequests?embed=metadata,patron,capabilities,library' |
343 |
).done(function() { |
344 |
var data = JSON.parse(ajax.responseText); |
345 |
// Make a copy, we'll be removing columns next and need |
346 |
// to be able to refer to data that has been removed |
347 |
var dataCopy = $.extend(true, [], data); |
348 |
// Remove all columns we're not interested in |
349 |
removeIgnore(dataCopy); |
350 |
// Expand columns that need it and create an array |
351 |
// of all column names |
352 |
$.each(dataCopy, function(k, row) { |
353 |
expandExpand(row); |
354 |
}); |
355 |
|
356 |
// Assemble an array of column definitions for passing |
357 |
// to datatables |
358 |
var colData = []; |
359 |
Object.keys(allCols).forEach(function(thisCol) { |
360 |
// Create the base column object |
361 |
var colObj = { |
362 |
name: thisCol, |
363 |
className: thisCol, |
364 |
defaultContent: '' |
365 |
}; |
366 |
// We may need to process the data going in this |
367 |
// column, so do it if necessary |
368 |
if ( |
369 |
specialCols.hasOwnProperty(thisCol) && |
370 |
specialCols[thisCol].hasOwnProperty('func') |
371 |
) { |
372 |
colObj.render = specialCols[thisCol].func; |
373 |
} else { |
374 |
colObj.data = thisCol; |
375 |
} |
376 |
colData.push(colObj); |
377 |
}); |
378 |
|
379 |
// Initialise the datatable |
380 |
table = $('#ill-requests').DataTable($.extend(true, {}, dataTablesDefaults, { |
381 |
'aoColumnDefs': [ |
382 |
{ // Last column shouldn't be sortable or searchable |
383 |
'aTargets': [ 'actions' ], |
384 |
'bSortable': false, |
385 |
'bSearchable': false |
386 |
}, |
387 |
{ // Hide the two date columns we use just for sorting |
388 |
'aTargets': [ 'placed', 'updated' ], |
389 |
'bVisible': false, |
390 |
'bSearchable': true |
391 |
}, |
392 |
{ // When sorting 'placed', we want to use the |
393 |
// unformatted column |
394 |
'aTargets': [ 'placed_formatted'], |
395 |
'iDataSort': 7 |
396 |
}, |
397 |
{ // When sorting 'updated', we want to use the |
398 |
// unformatted column |
399 |
'aTargets': [ 'updated_formatted'], |
400 |
'iDataSort': 9 |
401 |
} |
402 |
], |
403 |
'aaSorting': [[ 9, 'desc' ]], // Default sort, updated descending |
404 |
'processing': true, // Display a message when manipulating |
405 |
'iDisplayLength': 10, // 10 results per page |
406 |
'sPaginationType': "full_numbers", // Pagination display |
407 |
'deferRender': true, // Improve performance on big datasets |
408 |
'data': dataCopy, |
409 |
'columns': colData, |
410 |
'originalData': data, // Enable render functions to access |
411 |
// our original data |
412 |
'initComplete': function() { |
413 |
|
414 |
// Prepare any filter elements that need it |
415 |
for (var el in filterable) { |
416 |
if (filterable.hasOwnProperty(el)) { |
417 |
if (filterable[el].hasOwnProperty('prep')) { |
418 |
filterable[el].prep(dataCopy, data); |
419 |
} |
420 |
if (filterable[el].hasOwnProperty('listener')) { |
421 |
filterable[el].listener(); |
422 |
} |
423 |
} |
424 |
} |
425 |
|
426 |
} |
427 |
})); |
428 |
|
429 |
// Custom date range filtering |
430 |
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) { |
431 |
var placedStart = $('#illfilter_dateplaced_start').datepicker('getDate'); |
432 |
var placedEnd = $('#illfilter_dateplaced_end').datepicker('getDate'); |
433 |
var modifiedStart = $('#illfilter_datemodified_start').datepicker('getDate'); |
434 |
var modifiedEnd = $('#illfilter_datemodified_end').datepicker('getDate'); |
435 |
var rowPlaced = data[7] ? new Date(data[7]) : null; |
436 |
var rowModified = data[9] ? new Date(data[9]) : null; |
437 |
var placedPassed = true; |
438 |
var modifiedPassed = true; |
439 |
if (placedStart && rowPlaced && rowPlaced < placedStart) { |
440 |
placedPassed = false |
441 |
}; |
442 |
if (placedEnd && rowPlaced && rowPlaced > placedEnd) { |
443 |
placedPassed = false; |
444 |
} |
445 |
if (modifiedStart && rowModified && rowModified < modifiedStart) { |
446 |
modifiedPassed = false |
447 |
}; |
448 |
if (modifiedEnd && rowModified && rowModified > modifiedEnd) { |
449 |
modifiedPassed = false; |
450 |
} |
451 |
|
452 |
return placedPassed && modifiedPassed; |
453 |
|
454 |
}); |
455 |
|
456 |
} |
457 |
); |
458 |
|
459 |
var clearSearch = function() { |
460 |
table.search('').columns().search(''); |
461 |
activeFilters = {}; |
462 |
for (var filter in filterable) { |
463 |
if ( |
464 |
filterable.hasOwnProperty(filter) && |
465 |
filterable[filter].hasOwnProperty('clear') |
466 |
) { |
467 |
filterable[filter].clear(); |
468 |
} |
469 |
} |
470 |
table.draw(); |
471 |
}; |
472 |
|
473 |
// Apply any search filters, or clear any previous |
474 |
// ones |
475 |
$('#illfilter_form').submit(function(event) { |
476 |
event.preventDefault(); |
477 |
table.search('').columns().search(''); |
478 |
for (var active in activeFilters) { |
479 |
if (activeFilters.hasOwnProperty(active)) { |
480 |
activeFilters[active](); |
481 |
} |
482 |
} |
483 |
table.draw(); |
484 |
}); |
485 |
|
486 |
// Clear all filters |
487 |
$('#clear_search').click(function() { |
488 |
clearSearch(); |
489 |
}); |
490 |
|
491 |
}); |
492 |
//]]> |
493 |
</script> |
494 |
</head> |
10 |
</head> |
495 |
|
11 |
|
496 |
<body id="illrequests" class="ill"> |
12 |
<body id="illrequests" class="ill"> |
Lines 523-541
Link Here
|
523 |
</li> |
39 |
</li> |
524 |
<li> |
40 |
<li> |
525 |
<label for="illfilter_dateplaced_start">Date placed between:</label> |
41 |
<label for="illfilter_dateplaced_start">Date placed between:</label> |
526 |
<input type="text" name="illfilter_dateplaced_start" id="illfilter_dateplaced_start" class="datepicker"> |
42 |
<input type="text" name="illfilter_dateplaced_start" id="illfilter_dateplaced_start" class="datepicker" /> |
527 |
</li> |
43 |
</li> |
528 |
<li> |
44 |
<li> |
529 |
<label for="illfilter_dateplaced_end">and:</label> |
45 |
<label for="illfilter_dateplaced_end">and:</label> |
530 |
<input type="text" name="illfilter_dateplaced_end" id="illfilter_dateplaced_end" class="datepicker"> |
46 |
<input type="text" name="illfilter_dateplaced_end" id="illfilter_dateplaced_end" class="datepicker" /> |
531 |
</li> |
47 |
</li> |
532 |
<li> |
48 |
<li> |
533 |
<label for="illfilter_datemodified_start">Updated between:</label> |
49 |
<label for="illfilter_datemodified_start">Updated between:</label> |
534 |
<input type="text" name="illfilter_datemodified_start" id="illfilter_datemodified_start" class="datepicker"> |
50 |
<input type="text" name="illfilter_datemodified_start" id="illfilter_datemodified_start" class="datepicker" /> |
535 |
</li> |
51 |
</li> |
536 |
<li> |
52 |
<li> |
537 |
<label for="illfilter_datemodified_end">and:</label> |
53 |
<label for="illfilter_datemodified_end">and:</label> |
538 |
<input type="text" name="illfilter_datemodified_end" id="illfilter_datemodified_end" class="datepicker"> |
54 |
<input type="text" name="illfilter_datemodified_end" id="illfilter_datemodified_end" class="datepicker" /> |
539 |
</li> |
55 |
</li> |
540 |
<li> |
56 |
<li> |
541 |
<label for="illfilter_branchname">Library:</label> |
57 |
<label for="illfilter_branchname">Library:</label> |
Lines 545-551
Link Here
|
545 |
</li> |
61 |
</li> |
546 |
<li> |
62 |
<li> |
547 |
<label for="illfilter_barcode">Patron barcode:</label> |
63 |
<label for="illfilter_barcode">Patron barcode:</label> |
548 |
<input type="text" name="illfilter_barcode" id="illfilter_barcode"> |
64 |
<input type="text" name="illfilter_barcode" id="illfilter_barcode" /> |
549 |
</li> |
65 |
</li> |
550 |
</ol> |
66 |
</ol> |
551 |
<fieldset class="action"> |
67 |
<fieldset class="action"> |
Lines 623-629
Link Here
|
623 |
<ol> |
139 |
<ol> |
624 |
<li> |
140 |
<li> |
625 |
<label for="partner_filter">Filter partner libraries:</label> |
141 |
<label for="partner_filter">Filter partner libraries:</label> |
626 |
<input type="text" id="partner_filter"> |
142 |
<input type="text" id="partner_filter" /> |
627 |
</li> |
143 |
</li> |
628 |
<li> |
144 |
<li> |
629 |
<label for="partners" class="required">Select partner libraries:</label> |
145 |
<label for="partners" class="required">Select partner libraries:</label> |
Lines 637-643
Link Here
|
637 |
|
153 |
|
638 |
</li> |
154 |
</li> |
639 |
<li> |
155 |
<li> |
640 |
<label for="subject" class="required">Subject Line</label> |
156 |
<label for="subject" class="required">Subject line</label> |
641 |
<input type="text" name="subject" id="subject" type="text" value="[% whole.value.draft.subject %]" required="required" /> |
157 |
<input type="text" name="subject" id="subject" type="text" value="[% whole.value.draft.subject %]" required="required" /> |
642 |
</li> |
158 |
</li> |
643 |
<li> |
159 |
<li> |
Lines 645-656
Link Here
|
645 |
<textarea name="body" id="body" rows="20" cols="80" required="required">[% whole.value.draft.body %]</textarea> |
161 |
<textarea name="body" id="body" rows="20" cols="80" required="required">[% whole.value.draft.body %]</textarea> |
646 |
</li> |
162 |
</li> |
647 |
</ol> |
163 |
</ol> |
648 |
<input type="hidden" value="generic_confirm" name="method"> |
164 |
<input type="hidden" value="generic_confirm" name="method" /> |
649 |
<input type="hidden" value="draft" name="stage"> |
165 |
<input type="hidden" value="draft" name="stage" /> |
650 |
<input type="hidden" value="[% request.illrequest_id %]" name="illrequest_id"> |
166 |
<input type="hidden" value="[% request.illrequest_id %]" name="illrequest_id" /> |
651 |
</fieldset> |
167 |
</fieldset> |
652 |
<fieldset class="action"> |
168 |
<fieldset class="action"> |
653 |
<input type="submit" class="btn btn-default" value="Send email"/> |
169 |
<input type="submit" class="btn btn-default" value="Send email" /> |
654 |
<span><a href="[% ill_url %]" title="Return to request details">Cancel</a></span> |
170 |
<span><a href="[% ill_url %]" title="Return to request details">Cancel</a></span> |
655 |
</fieldset> |
171 |
</fieldset> |
656 |
</form> |
172 |
</form> |
Lines 671-681
Link Here
|
671 |
<ol> |
187 |
<ol> |
672 |
<li class="borrowernumber"> |
188 |
<li class="borrowernumber"> |
673 |
<label for="borrowernumber">Patron ID:</label> |
189 |
<label for="borrowernumber">Patron ID:</label> |
674 |
<input name="borrowernumber" id="borrowernumber" type="text" value="[% request.borrowernumber %]"> |
190 |
<input name="borrowernumber" id="borrowernumber" type="text" value="[% request.borrowernumber %]" /> |
675 |
</li> |
191 |
</li> |
676 |
<li class="biblio_id"> |
192 |
<li class="biblio_id"> |
677 |
<label for="biblio_id" class="biblio_id">Biblio ID:</label> |
193 |
<label for="biblio_id" class="biblio_id">Biblio ID:</label> |
678 |
<input name="biblio_id" id="biblio_id" type="text" value="[% request.biblio_id %]"> |
194 |
<input name="biblio_id" id="biblio_id" type="text" value="[% request.biblio_id %]" /> |
679 |
</li> |
195 |
</li> |
680 |
<li class="branchcode"> |
196 |
<li class="branchcode"> |
681 |
<label for="library" class="branchcode">Library:</label> |
197 |
<label for="library" class="branchcode">Library:</label> |
Lines 715-724
Link Here
|
715 |
</ol> |
231 |
</ol> |
716 |
</fieldset> |
232 |
</fieldset> |
717 |
<fieldset class="action"> |
233 |
<fieldset class="action"> |
718 |
<input type="hidden" value="edit_action" name="method"> |
234 |
<input type="hidden" value="edit_action" name="method" /> |
719 |
<input type="hidden" value="form" name="stage"> |
235 |
<input type="hidden" value="form" name="stage" /> |
720 |
<input type="hidden" value="[% request.illrequest_id %]" name="illrequest_id"> |
236 |
<input type="hidden" value="[% request.illrequest_id %]" name="illrequest_id" /> |
721 |
<input type="submit" value="Submit"> |
237 |
<input type="submit" value="Submit" /> |
722 |
<a class="cancel" href="/cgi-bin/koha/ill/ill-requests.pl?method=illview&illrequest_id=[% request.id %]">Cancel</a> |
238 |
<a class="cancel" href="/cgi-bin/koha/ill/ill-requests.pl?method=illview&illrequest_id=[% request.id %]">Cancel</a> |
723 |
</fieldset> |
239 |
</fieldset> |
724 |
</form> |
240 |
</form> |
Lines 879-882
Link Here
|
879 |
[% CATCH %] |
395 |
[% CATCH %] |
880 |
[% END %] |
396 |
[% END %] |
881 |
|
397 |
|
|
|
398 |
[% MACRO jsinclude BLOCK %] |
399 |
[% INCLUDE 'datatables.inc' %] |
400 |
[% INCLUDE 'calendar.inc' %] |
401 |
<script> |
402 |
$(document).ready(function() { |
403 |
|
404 |
// Illview Datatable setup |
405 |
|
406 |
var table; |
407 |
|
408 |
// Filters that are active |
409 |
var activeFilters = {}; |
410 |
|
411 |
// Fields we don't want to display |
412 |
var ignore = [ |
413 |
'accessurl', |
414 |
'backend', |
415 |
'branchcode', |
416 |
'completed', |
417 |
'capabilities', |
418 |
'cost', |
419 |
'medium', |
420 |
'notesopac', |
421 |
'notesstaff', |
422 |
'replied' |
423 |
]; |
424 |
|
425 |
// Fields we need to expand (flatten) |
426 |
var expand = [ |
427 |
'metadata', |
428 |
'patron' |
429 |
]; |
430 |
|
431 |
// Expanded fields |
432 |
// This is auto populated |
433 |
var expanded = {}; |
434 |
|
435 |
// The core fields that should be displayed first |
436 |
var core = [ |
437 |
'metadata_Author', |
438 |
'metadata_Title', |
439 |
'borrowername', |
440 |
'patron_cardnumber', |
441 |
'biblio_id', |
442 |
'library', |
443 |
'status', |
444 |
'placed', |
445 |
'placed_formatted', |
446 |
'updated', |
447 |
'updated_formatted', |
448 |
'illrequest_id', |
449 |
'action' |
450 |
]; |
451 |
|
452 |
// Filterable columns |
453 |
var filterable = { |
454 |
status: { |
455 |
prep: function(tableData, oData) { |
456 |
var uniques = {}; |
457 |
tableData.forEach(function(row) { |
458 |
var resolvedName = getStatusName( |
459 |
oData[0].capabilities[row.status].name |
460 |
); |
461 |
uniques[resolvedName] = 1 |
462 |
}); |
463 |
Object.keys(uniques).sort().forEach(function(unique) { |
464 |
$('#illfilter_status').append( |
465 |
'<option value="' + unique + |
466 |
'">' + unique + '</option>' |
467 |
); |
468 |
}); |
469 |
}, |
470 |
listener: function() { |
471 |
var me = 'status'; |
472 |
$('#illfilter_status').change(function() { |
473 |
var sel = $('#illfilter_status option:selected').val(); |
474 |
if (sel && sel.length > 0) { |
475 |
activeFilters[me] = function() { |
476 |
table.column(6).search(sel); |
477 |
} |
478 |
} else { |
479 |
if (activeFilters.hasOwnProperty(me)) { |
480 |
delete activeFilters[me]; |
481 |
} |
482 |
} |
483 |
}); |
484 |
}, |
485 |
clear: function() { |
486 |
$('#illfilter_status').val(''); |
487 |
} |
488 |
}, |
489 |
pickupBranch: { |
490 |
prep: function(tableData, oData) { |
491 |
var uniques = {}; |
492 |
tableData.forEach(function(row) { |
493 |
uniques[row.library.branchname] = 1 |
494 |
}); |
495 |
Object.keys(uniques).sort().forEach(function(unique) { |
496 |
$('#illfilter_branchname').append( |
497 |
'<option value="' + unique + |
498 |
'">' + unique + '</option>' |
499 |
); |
500 |
}); |
501 |
}, |
502 |
listener: function() { |
503 |
var me = 'pickupBranch'; |
504 |
$('#illfilter_branchname').change(function() { |
505 |
var sel = $('#illfilter_branchname option:selected').val(); |
506 |
if (sel && sel.length > 0) { |
507 |
activeFilters[me] = function() { |
508 |
table.column(5).search(sel); |
509 |
} |
510 |
} else { |
511 |
if (activeFilters.hasOwnProperty(me)) { |
512 |
delete activeFilters[me]; |
513 |
} |
514 |
} |
515 |
}); |
516 |
}, |
517 |
clear: function() { |
518 |
$('#illfilter_branchname').val(''); |
519 |
} |
520 |
}, |
521 |
barcode: { |
522 |
listener: function() { |
523 |
var me = 'barcode'; |
524 |
$('#illfilter_barcode').change(function() { |
525 |
var val = $('#illfilter_barcode').val(); |
526 |
if (val && val.length > 0) { |
527 |
activeFilters[me] = function() { |
528 |
table.column(3).search(val); |
529 |
} |
530 |
} else { |
531 |
if (activeFilters.hasOwnProperty(me)) { |
532 |
delete activeFilters[me]; |
533 |
} |
534 |
} |
535 |
}); |
536 |
}, |
537 |
clear: function() { |
538 |
$('#illfilter_barcode').val(''); |
539 |
} |
540 |
}, |
541 |
dateModified: { |
542 |
clear: function() { |
543 |
$('#illfilter_datemodified_start, #illfilter_datemodified_end').val(''); |
544 |
} |
545 |
}, |
546 |
datePlaced: { |
547 |
clear: function() { |
548 |
$('#illfilter_dateplaced_start, #illfilter_dateplaced_end').val(''); |
549 |
} |
550 |
} |
551 |
}; |
552 |
|
553 |
// Remove any fields we're ignoring |
554 |
var removeIgnore = function(dataObj) { |
555 |
dataObj.forEach(function(thisRow) { |
556 |
ignore.forEach(function(thisIgnore) { |
557 |
if (thisRow.hasOwnProperty(thisIgnore)) { |
558 |
delete thisRow[thisIgnore]; |
559 |
} |
560 |
}); |
561 |
}); |
562 |
}; |
563 |
|
564 |
// Expand any fields we're expanding |
565 |
var expandExpand = function(row) { |
566 |
expand.forEach(function(thisExpand) { |
567 |
if (row.hasOwnProperty(thisExpand)) { |
568 |
if (!expanded.hasOwnProperty(thisExpand)) { |
569 |
expanded[thisExpand] = []; |
570 |
} |
571 |
var expandObj = row[thisExpand]; |
572 |
Object.keys(expandObj).forEach( |
573 |
function(thisExpandCol) { |
574 |
var expColName = thisExpand + '_' + thisExpandCol; |
575 |
// Keep a list of fields that have been expanded |
576 |
// so we can create toggle links for them |
577 |
if (expanded[thisExpand].indexOf(expColName) == -1) { |
578 |
expanded[thisExpand].push(expColName); |
579 |
} |
580 |
expandObj[expColName] = |
581 |
expandObj[thisExpandCol]; |
582 |
delete expandObj[thisExpandCol]; |
583 |
} |
584 |
); |
585 |
$.extend(true, row, expandObj); |
586 |
delete row[thisExpand]; |
587 |
} |
588 |
}); |
589 |
}; |
590 |
|
591 |
// Build a de-duped list of all column names |
592 |
var allCols = {}; |
593 |
core.map(function(thisCore) { |
594 |
allCols[thisCore] = 1; |
595 |
}); |
596 |
|
597 |
// Strip the expand prefix if it exists, we do this for display |
598 |
var stripPrefix = function(value) { |
599 |
expand.forEach(function(thisExpand) { |
600 |
var regex = new RegExp(thisExpand + '_', 'g'); |
601 |
value = value.replace(regex, ''); |
602 |
}); |
603 |
return value; |
604 |
}; |
605 |
|
606 |
// Our 'render' function for borrowerlink |
607 |
var createPatronLink = function(data, type, row) { |
608 |
return '<a title="' + _("View borrower details") + '" ' + |
609 |
'href="/cgi-bin/koha/members/moremember.pl?' + |
610 |
'borrowernumber='+row.borrowernumber+'">' + |
611 |
row.patron_firstname + ' ' + row.patron_surname + |
612 |
'</a>'; |
613 |
}; |
614 |
|
615 |
// Our 'render' function for the library name |
616 |
var createLibrary = function(data, type, row) { |
617 |
return row.library.branchname; |
618 |
}; |
619 |
|
620 |
// Render function for request ID |
621 |
var createRequestId = function(data, type, row) { |
622 |
return row.id_prefix + row.illrequest_id; |
623 |
}; |
624 |
|
625 |
// Render function for request status |
626 |
var createStatus = function(data, type, row, meta) { |
627 |
var origData = meta.settings.oInit.originalData; |
628 |
if (origData.length > 0) { |
629 |
var status_name = meta.settings.oInit.originalData[0].capabilities[ |
630 |
row.status |
631 |
].name; |
632 |
return getStatusName(status_name); |
633 |
} else { |
634 |
return ''; |
635 |
} |
636 |
}; |
637 |
|
638 |
var getStatusName = function(origName) { |
639 |
switch( origName ) { |
640 |
case "New request": |
641 |
return _("New request"); |
642 |
case "Requested": |
643 |
return _("Requested"); |
644 |
case "Requested from partners": |
645 |
return _("Requested from partners"); |
646 |
case "Request reverted": |
647 |
return _("Request reverted"); |
648 |
case "Queued request": |
649 |
return _("Queued request"); |
650 |
case "Cancellation requested": |
651 |
return _("Cancellation requested"); |
652 |
case "Completed": |
653 |
return _("Completed"); |
654 |
case "Delete request": |
655 |
return _("Delete request"); |
656 |
default: |
657 |
return origName; |
658 |
} |
659 |
}; |
660 |
|
661 |
// Render function for creating a row's action link |
662 |
var createActionLink = function(data, type, row) { |
663 |
return '<a class="btn btn-default btn-sm" ' + |
664 |
'href="/cgi-bin/koha/ill/ill-requests.pl?' + |
665 |
'method=illview&illrequest_id=' + |
666 |
row.illrequest_id + |
667 |
'">' + _("Manage request") + '</a>'; |
668 |
}; |
669 |
|
670 |
// Columns that require special treatment |
671 |
var specialCols = { |
672 |
action: { |
673 |
name: '', |
674 |
func: createActionLink |
675 |
}, |
676 |
borrowername: { |
677 |
name: _("Patron"), |
678 |
func: createPatronLink |
679 |
}, |
680 |
illrequest_id: { |
681 |
name: _("Request number"), |
682 |
func: createRequestId |
683 |
}, |
684 |
status: { |
685 |
name: _("Status"), |
686 |
func: createStatus |
687 |
}, |
688 |
biblio_id: { |
689 |
name: _("Biblio ID") |
690 |
}, |
691 |
library: { |
692 |
name: _("Library"), |
693 |
func: createLibrary |
694 |
}, |
695 |
updated: { |
696 |
name: _("Updated on"), |
697 |
}, |
698 |
patron_cardnumber: { |
699 |
name: _("Patron barcode") |
700 |
} |
701 |
}; |
702 |
|
703 |
// Toggle request attributes in Illview |
704 |
$('#toggle_requestattributes').on('click', function(e) { |
705 |
e.preventDefault(); |
706 |
$('#requestattributes').toggleClass('content_hidden'); |
707 |
}); |
708 |
|
709 |
// Filter partner list |
710 |
$('#partner_filter').keyup(function() { |
711 |
var needle = $('#partner_filter').val(); |
712 |
$('#partners > option').each(function() { |
713 |
var regex = new RegExp(needle, 'i'); |
714 |
if ( |
715 |
needle.length == 0 || |
716 |
$(this).is(':selected') || |
717 |
$(this).text().match(regex) |
718 |
) { |
719 |
$(this).show(); |
720 |
} else { |
721 |
$(this).hide(); |
722 |
} |
723 |
}); |
724 |
}); |
725 |
|
726 |
// Get our data from the API and process it prior to passing |
727 |
// it to datatables |
728 |
var ajax = $.ajax( |
729 |
'/api/v1/illrequests?embed=metadata,patron,capabilities,library' |
730 |
).done(function() { |
731 |
var data = JSON.parse(ajax.responseText); |
732 |
// Make a copy, we'll be removing columns next and need |
733 |
// to be able to refer to data that has been removed |
734 |
var dataCopy = $.extend(true, [], data); |
735 |
// Remove all columns we're not interested in |
736 |
removeIgnore(dataCopy); |
737 |
// Expand columns that need it and create an array |
738 |
// of all column names |
739 |
$.each(dataCopy, function(k, row) { |
740 |
expandExpand(row); |
741 |
}); |
742 |
|
743 |
// Assemble an array of column definitions for passing |
744 |
// to datatables |
745 |
var colData = []; |
746 |
Object.keys(allCols).forEach(function(thisCol) { |
747 |
// Create the base column object |
748 |
var colObj = { |
749 |
name: thisCol, |
750 |
className: thisCol, |
751 |
defaultContent: '' |
752 |
}; |
753 |
// We may need to process the data going in this |
754 |
// column, so do it if necessary |
755 |
if ( |
756 |
specialCols.hasOwnProperty(thisCol) && |
757 |
specialCols[thisCol].hasOwnProperty('func') |
758 |
) { |
759 |
colObj.render = specialCols[thisCol].func; |
760 |
} else { |
761 |
colObj.data = thisCol; |
762 |
} |
763 |
colData.push(colObj); |
764 |
}); |
765 |
|
766 |
// Initialise the datatable |
767 |
table = $('#ill-requests').DataTable($.extend(true, {}, dataTablesDefaults, { |
768 |
'aoColumnDefs': [ |
769 |
{ // Last column shouldn't be sortable or searchable |
770 |
'aTargets': [ 'actions' ], |
771 |
'bSortable': false, |
772 |
'bSearchable': false |
773 |
}, |
774 |
{ // Hide the two date columns we use just for sorting |
775 |
'aTargets': [ 'placed', 'updated' ], |
776 |
'bVisible': false, |
777 |
'bSearchable': true |
778 |
}, |
779 |
{ // When sorting 'placed', we want to use the |
780 |
// unformatted column |
781 |
'aTargets': [ 'placed_formatted'], |
782 |
'iDataSort': 7 |
783 |
}, |
784 |
{ // When sorting 'updated', we want to use the |
785 |
// unformatted column |
786 |
'aTargets': [ 'updated_formatted'], |
787 |
'iDataSort': 9 |
788 |
} |
789 |
], |
790 |
'aaSorting': [[ 9, 'desc' ]], // Default sort, updated descending |
791 |
'processing': true, // Display a message when manipulating |
792 |
'sPaginationType': "full_numbers", // Pagination display |
793 |
'deferRender': true, // Improve performance on big datasets |
794 |
'data': dataCopy, |
795 |
'columns': colData, |
796 |
'originalData': data, // Enable render functions to access |
797 |
// our original data |
798 |
'initComplete': function() { |
799 |
|
800 |
// Prepare any filter elements that need it |
801 |
for (var el in filterable) { |
802 |
if (filterable.hasOwnProperty(el)) { |
803 |
if (filterable[el].hasOwnProperty('prep')) { |
804 |
filterable[el].prep(dataCopy, data); |
805 |
} |
806 |
if (filterable[el].hasOwnProperty('listener')) { |
807 |
filterable[el].listener(); |
808 |
} |
809 |
} |
810 |
} |
811 |
|
812 |
} |
813 |
})); |
814 |
|
815 |
// Custom date range filtering |
816 |
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) { |
817 |
var placedStart = $('#illfilter_dateplaced_start').datepicker('getDate'); |
818 |
var placedEnd = $('#illfilter_dateplaced_end').datepicker('getDate'); |
819 |
var modifiedStart = $('#illfilter_datemodified_start').datepicker('getDate'); |
820 |
var modifiedEnd = $('#illfilter_datemodified_end').datepicker('getDate'); |
821 |
var rowPlaced = data[7] ? new Date(data[7]) : null; |
822 |
var rowModified = data[9] ? new Date(data[9]) : null; |
823 |
var placedPassed = true; |
824 |
var modifiedPassed = true; |
825 |
if (placedStart && rowPlaced && rowPlaced < placedStart) { |
826 |
placedPassed = false |
827 |
}; |
828 |
if (placedEnd && rowPlaced && rowPlaced > placedEnd) { |
829 |
placedPassed = false; |
830 |
} |
831 |
if (modifiedStart && rowModified && rowModified < modifiedStart) { |
832 |
modifiedPassed = false |
833 |
}; |
834 |
if (modifiedEnd && rowModified && rowModified > modifiedEnd) { |
835 |
modifiedPassed = false; |
836 |
} |
837 |
|
838 |
return placedPassed && modifiedPassed; |
839 |
|
840 |
}); |
841 |
|
842 |
} |
843 |
); |
844 |
|
845 |
var clearSearch = function() { |
846 |
table.search('').columns().search(''); |
847 |
activeFilters = {}; |
848 |
for (var filter in filterable) { |
849 |
if ( |
850 |
filterable.hasOwnProperty(filter) && |
851 |
filterable[filter].hasOwnProperty('clear') |
852 |
) { |
853 |
filterable[filter].clear(); |
854 |
} |
855 |
} |
856 |
table.draw(); |
857 |
}; |
858 |
|
859 |
// Apply any search filters, or clear any previous |
860 |
// ones |
861 |
$('#illfilter_form').submit(function(event) { |
862 |
event.preventDefault(); |
863 |
table.search('').columns().search(''); |
864 |
for (var active in activeFilters) { |
865 |
if (activeFilters.hasOwnProperty(active)) { |
866 |
activeFilters[active](); |
867 |
} |
868 |
} |
869 |
table.draw(); |
870 |
}); |
871 |
|
872 |
// Clear all filters |
873 |
$('#clear_search').click(function() { |
874 |
clearSearch(); |
875 |
}); |
876 |
|
877 |
}); |
878 |
</script> |
879 |
[% END %] |
880 |
|
882 |
[% INCLUDE 'intranet-bottom.inc' %] |
881 |
[% INCLUDE 'intranet-bottom.inc' %] |
883 |
- |
|
|