View | Details | Raw Unified | Return to bug 20600
Collapse All | Expand All

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt (-504 / +502 lines)
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 &rsaquo; ILL requests  &rsaquo;</title>
7
<title>Koha &rsaquo; 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&amp;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&amp;illrequest_id=[% request.id %]">Cancel</a>
238
                            <a class="cancel" href="/cgi-bin/koha/ill/ill-requests.pl?method=illview&amp;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&amp;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
- 

Return to bug 20600