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 / +508 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
        // Filter partner list
317
        $('#partner_filter').keyup(function() {
318
            var needle = $('#partner_filter').val();
319
            $('#partners > option').each(function() {
320
                var regex = new RegExp(needle, 'i');
321
                if (
322
                    needle.length == 0 ||
323
                    $(this).is(':selected') ||
324
                    $(this).text().match(regex)
325
                ) {
326
                    $(this).show();
327
                } else {
328
                    $(this).hide();
329
                }
330
            });
331
        });
332
333
        // Display the modal containing request supplier metadata
334
        $('#ill-request-display-metadata').on('click', function(e) {
335
            e.preventDefault();
336
            $('#dataPreview').modal({show:true});
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 895-898 Link Here
895
[% CATCH %]
411
[% CATCH %]
896
[% END %]
412
[% END %]
897
413
414
[% MACRO jsinclude BLOCK %]
415
    [% INCLUDE 'datatables.inc' %]
416
    [% INCLUDE 'calendar.inc' %]
417
    <script>
418
        $(document).ready(function() {
419
420
            // Illview Datatable setup
421
422
            var table;
423
424
            // Filters that are active
425
            var activeFilters = {};
426
427
            // Fields we don't want to display
428
            var ignore = [
429
                'accessurl',
430
                'backend',
431
                'branchcode',
432
                'completed',
433
                'capabilities',
434
                'cost',
435
                'medium',
436
                'notesopac',
437
                'notesstaff',
438
                'replied'
439
            ];
440
441
            // Fields we need to expand (flatten)
442
            var expand = [
443
                'metadata',
444
                'patron'
445
            ];
446
447
            // Expanded fields
448
            // This is auto populated
449
            var expanded = {};
450
451
            // The core fields that should be displayed first
452
            var core = [
453
                'metadata_Author',
454
                'metadata_Title',
455
                'borrowername',
456
                'patron_cardnumber',
457
                'biblio_id',
458
                'library',
459
                'status',
460
                'placed',
461
                'placed_formatted',
462
                'updated',
463
                'updated_formatted',
464
                'illrequest_id',
465
                'action'
466
            ];
467
468
            // Filterable columns
469
            var filterable = {
470
                status: {
471
                    prep: function(tableData, oData) {
472
                        var uniques = {};
473
                        tableData.forEach(function(row) {
474
                            var resolvedName = getStatusName(
475
                                oData[0].capabilities[row.status].name
476
                            );
477
                            uniques[resolvedName] = 1
478
                        });
479
                        Object.keys(uniques).sort().forEach(function(unique) {
480
                            $('#illfilter_status').append(
481
                                '<option value="' + unique  +
482
                                '">' + unique +  '</option>'
483
                            );
484
                        });
485
                    },
486
                    listener: function() {
487
                        var me = 'status';
488
                        $('#illfilter_status').change(function() {
489
                            var sel = $('#illfilter_status option:selected').val();
490
                            if (sel && sel.length > 0) {
491
                                activeFilters[me] = function() {
492
                                    table.column(6).search(sel);
493
                                }
494
                            } else {
495
                                if (activeFilters.hasOwnProperty(me)) {
496
                                    delete activeFilters[me];
497
                                }
498
                            }
499
                        });
500
                    },
501
                    clear: function() {
502
                        $('#illfilter_status').val('');
503
                    }
504
                },
505
                pickupBranch: {
506
                    prep: function(tableData, oData) {
507
                        var uniques = {};
508
                        tableData.forEach(function(row) {
509
                            uniques[row.library.branchname] = 1
510
                        });
511
                        Object.keys(uniques).sort().forEach(function(unique) {
512
                            $('#illfilter_branchname').append(
513
                                '<option value="' + unique  +
514
                                '">' + unique +  '</option>'
515
                            );
516
                        });
517
                    },
518
                    listener: function() {
519
                        var me = 'pickupBranch';
520
                        $('#illfilter_branchname').change(function() {
521
                            var sel = $('#illfilter_branchname option:selected').val();
522
                            if (sel && sel.length > 0) {
523
                                activeFilters[me] = function() {
524
                                    table.column(5).search(sel);
525
                                }
526
                            } else {
527
                                if (activeFilters.hasOwnProperty(me)) {
528
                                    delete activeFilters[me];
529
                                }
530
                            }
531
                        });
532
                    },
533
                    clear: function() {
534
                        $('#illfilter_branchname').val('');
535
                    }
536
                },
537
                barcode: {
538
                    listener: function() {
539
                        var me = 'barcode';
540
                        $('#illfilter_barcode').change(function() {
541
                            var val = $('#illfilter_barcode').val();
542
                            if (val && val.length > 0) {
543
                                activeFilters[me] = function() {
544
                                    table.column(3).search(val);
545
                                }
546
                            } else {
547
                                if (activeFilters.hasOwnProperty(me)) {
548
                                    delete activeFilters[me];
549
                                }
550
                            }
551
                        });
552
                    },
553
                    clear: function() {
554
                        $('#illfilter_barcode').val('');
555
                    }
556
                },
557
                dateModified: {
558
                    clear: function() {
559
                        $('#illfilter_datemodified_start, #illfilter_datemodified_end').val('');
560
                    }
561
                },
562
                datePlaced: {
563
                    clear: function() {
564
                        $('#illfilter_dateplaced_start, #illfilter_dateplaced_end').val('');
565
                    }
566
                }
567
            };
568
569
            // Remove any fields we're ignoring
570
            var removeIgnore = function(dataObj) {
571
                dataObj.forEach(function(thisRow) {
572
                    ignore.forEach(function(thisIgnore) {
573
                        if (thisRow.hasOwnProperty(thisIgnore)) {
574
                            delete thisRow[thisIgnore];
575
                        }
576
                    });
577
                });
578
            };
579
580
            // Expand any fields we're expanding
581
            var expandExpand = function(row) {
582
                expand.forEach(function(thisExpand) {
583
                    if (row.hasOwnProperty(thisExpand)) {
584
                        if (!expanded.hasOwnProperty(thisExpand)) {
585
                            expanded[thisExpand] = [];
586
                        }
587
                        var expandObj = row[thisExpand];
588
                        Object.keys(expandObj).forEach(
589
                            function(thisExpandCol) {
590
                                var expColName = thisExpand + '_' + thisExpandCol;
591
                                // Keep a list of fields that have been expanded
592
                                // so we can create toggle links for them
593
                                if (expanded[thisExpand].indexOf(expColName) == -1) {
594
                                    expanded[thisExpand].push(expColName);
595
                                }
596
                                expandObj[expColName] =
597
                                    expandObj[thisExpandCol];
598
                                delete expandObj[thisExpandCol];
599
                            }
600
                        );
601
                        $.extend(true, row, expandObj);
602
                        delete row[thisExpand];
603
                    }
604
                });
605
            };
606
607
            // Build a de-duped list of all column names
608
            var allCols = {};
609
            core.map(function(thisCore) {
610
                allCols[thisCore] = 1;
611
            });
612
613
            // Strip the expand prefix if it exists, we do this for display
614
            var stripPrefix = function(value) {
615
                expand.forEach(function(thisExpand) {
616
                    var regex = new RegExp(thisExpand + '_', 'g');
617
                    value = value.replace(regex, '');
618
                });
619
                return value;
620
            };
621
622
            // Our 'render' function for borrowerlink
623
            var createPatronLink = function(data, type, row) {
624
                return '<a title="' + _("View borrower details") + '" ' +
625
                    'href="/cgi-bin/koha/members/moremember.pl?' +
626
                    'borrowernumber='+row.borrowernumber+'">' +
627
                    row.patron_firstname + ' ' + row.patron_surname +
628
                    '</a>';
629
            };
630
631
            // Our 'render' function for the library name
632
            var createLibrary = function(data, type, row) {
633
                return row.library.branchname;
634
            };
635
636
            // Render function for request ID
637
            var createRequestId = function(data, type, row) {
638
                return row.id_prefix + row.illrequest_id;
639
            };
640
641
            // Render function for request status
642
            var createStatus = function(data, type, row, meta) {
643
                var origData = meta.settings.oInit.originalData;
644
                if (origData.length > 0) {
645
                    var status_name = meta.settings.oInit.originalData[0].capabilities[
646
                        row.status
647
                    ].name;
648
                    return getStatusName(status_name);
649
                } else {
650
                    return '';
651
                }
652
            };
653
654
            var getStatusName = function(origName) {
655
                switch( origName ) {
656
                    case "New request":
657
                        return _("New request");
658
                    case "Requested":
659
                        return _("Requested");
660
                    case "Requested from partners":
661
                        return _("Requested from partners");
662
                    case "Request reverted":
663
                        return _("Request reverted");
664
                    case "Queued request":
665
                        return _("Queued request");
666
                    case "Cancellation requested":
667
                        return _("Cancellation requested");
668
                    case "Completed":
669
                        return _("Completed");
670
                    case "Delete request":
671
                        return _("Delete request");
672
                    default:
673
                        return origName;
674
                }
675
            };
676
677
            // Render function for creating a row's action link
678
            var createActionLink = function(data, type, row) {
679
                return '<a class="btn btn-default btn-sm" ' +
680
                    'href="/cgi-bin/koha/ill/ill-requests.pl?' +
681
                    'method=illview&amp;illrequest_id=' +
682
                    row.illrequest_id +
683
                    '">' + _("Manage request") + '</a>';
684
            };
685
686
            // Columns that require special treatment
687
            var specialCols = {
688
                action: {
689
                    name: '',
690
                    func: createActionLink
691
                },
692
                borrowername: {
693
                    name: _("Patron"),
694
                    func: createPatronLink
695
                },
696
                illrequest_id: {
697
                    name: _("Request number"),
698
                    func: createRequestId
699
                },
700
                status: {
701
                    name: _("Status"),
702
                    func: createStatus
703
                },
704
                biblio_id: {
705
                    name: _("Biblio ID")
706
                },
707
                library: {
708
                    name: _("Library"),
709
                    func: createLibrary
710
                },
711
                updated: {
712
                    name: _("Updated on"),
713
                },
714
                patron_cardnumber: {
715
                    name: _("Patron barcode")
716
                }
717
            };
718
719
            // Toggle request attributes in Illview
720
            $('#toggle_requestattributes').on('click', function(e) {
721
                e.preventDefault();
722
                $('#requestattributes').toggleClass('content_hidden');
723
            });
724
725
            // Filter partner list
726
            $('#partner_filter').keyup(function() {
727
                var needle = $('#partner_filter').val();
728
                $('#partners > option').each(function() {
729
                    var regex = new RegExp(needle, 'i');
730
                    if (
731
                        needle.length == 0 ||
732
                        $(this).is(':selected') ||
733
                        $(this).text().match(regex)
734
                    ) {
735
                        $(this).show();
736
                    } else {
737
                        $(this).hide();
738
                    }
739
                });
740
            });
741
742
        // Display the modal containing request supplier metadata
743
        $('#ill-request-display-metadata').on('click', function(e) {
744
            e.preventDefault();
745
            $('#dataPreview').modal({show:true});
746
        });
747
748
            // Get our data from the API and process it prior to passing
749
            // it to datatables
750
            var ajax = $.ajax(
751
                '/api/v1/illrequests?embed=metadata,patron,capabilities,library'
752
                ).done(function() {
753
                    var data = JSON.parse(ajax.responseText);
754
                    // Make a copy, we'll be removing columns next and need
755
                    // to be able to refer to data that has been removed
756
                    var dataCopy = $.extend(true, [], data);
757
                    // Remove all columns we're not interested in
758
                    removeIgnore(dataCopy);
759
                    // Expand columns that need it and create an array
760
                    // of all column names
761
                    $.each(dataCopy, function(k, row) {
762
                        expandExpand(row);
763
                    });
764
765
                    // Assemble an array of column definitions for passing
766
                    // to datatables
767
                    var colData = [];
768
                    Object.keys(allCols).forEach(function(thisCol) {
769
                        // Create the base column object
770
                        var colObj = {
771
                            name: thisCol,
772
                            className: thisCol,
773
                            defaultContent: ''
774
                        };
775
                        // We may need to process the data going in this
776
                        // column, so do it if necessary
777
                        if (
778
                            specialCols.hasOwnProperty(thisCol) &&
779
                            specialCols[thisCol].hasOwnProperty('func')
780
                        ) {
781
                            colObj.render = specialCols[thisCol].func;
782
                        } else {
783
                            colObj.data = thisCol;
784
                        }
785
                        colData.push(colObj);
786
                    });
787
788
                    // Initialise the datatable
789
                    table = $('#ill-requests').DataTable($.extend(true, {}, dataTablesDefaults, {
790
                        'aoColumnDefs': [
791
                            { // Last column shouldn't be sortable or searchable
792
                                'aTargets': [ 'actions' ],
793
                                'bSortable': false,
794
                                'bSearchable': false
795
                            },
796
                            { // Hide the two date columns we use just for sorting
797
                                'aTargets': [ 'placed', 'updated' ],
798
                                'bVisible': false,
799
                                'bSearchable': true
800
                            },
801
                            { // When sorting 'placed', we want to use the
802
                              // unformatted column
803
                              'aTargets': [ 'placed_formatted'],
804
                              'iDataSort': 7
805
                            },
806
                            { // When sorting 'updated', we want to use the
807
                              // unformatted column
808
                              'aTargets': [ 'updated_formatted'],
809
                              'iDataSort': 9
810
                            }
811
                        ],
812
                        'aaSorting': [[ 9, 'desc' ]], // Default sort, updated descending
813
                        'processing': true, // Display a message when manipulating
814
                        'sPaginationType': "full_numbers", // Pagination display
815
                        'deferRender': true, // Improve performance on big datasets
816
                        'data': dataCopy,
817
                        'columns': colData,
818
                        'originalData': data, // Enable render functions to access
819
                                              // our original data
820
                        'initComplete': function() {
821
822
                            // Prepare any filter elements that need it
823
                            for (var el in filterable) {
824
                                if (filterable.hasOwnProperty(el)) {
825
                                    if (filterable[el].hasOwnProperty('prep')) {
826
                                        filterable[el].prep(dataCopy, data);
827
                                    }
828
                                    if (filterable[el].hasOwnProperty('listener')) {
829
                                        filterable[el].listener();
830
                                    }
831
                                }
832
                            }
833
834
                        }
835
                    }));
836
837
                    // Custom date range filtering
838
                    $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
839
                        var placedStart = $('#illfilter_dateplaced_start').datepicker('getDate');
840
                        var placedEnd = $('#illfilter_dateplaced_end').datepicker('getDate');
841
                        var modifiedStart = $('#illfilter_datemodified_start').datepicker('getDate');
842
                        var modifiedEnd = $('#illfilter_datemodified_end').datepicker('getDate');
843
                        var rowPlaced = data[7] ? new Date(data[7]) : null;
844
                        var rowModified = data[9] ? new Date(data[9]) : null;
845
                        var placedPassed = true;
846
                        var modifiedPassed = true;
847
                        if (placedStart && rowPlaced && rowPlaced < placedStart) {
848
                            placedPassed = false
849
                        };
850
                        if (placedEnd && rowPlaced && rowPlaced > placedEnd) {
851
                            placedPassed = false;
852
                        }
853
                        if (modifiedStart && rowModified && rowModified < modifiedStart) {
854
                            modifiedPassed = false
855
                        };
856
                        if (modifiedEnd && rowModified && rowModified > modifiedEnd) {
857
                            modifiedPassed = false;
858
                        }
859
860
                        return placedPassed && modifiedPassed;
861
862
                    });
863
864
                }
865
            );
866
867
            var clearSearch = function() {
868
                table.search('').columns().search('');
869
                activeFilters = {};
870
                for (var filter in filterable) {
871
                    if (
872
                        filterable.hasOwnProperty(filter) &&
873
                        filterable[filter].hasOwnProperty('clear')
874
                    ) {
875
                        filterable[filter].clear();
876
                    }
877
                }
878
                table.draw();
879
            };
880
881
            // Apply any search filters, or clear any previous
882
            // ones
883
            $('#illfilter_form').submit(function(event) {
884
                event.preventDefault();
885
                table.search('').columns().search('');
886
                for (var active in activeFilters) {
887
                    if (activeFilters.hasOwnProperty(active)) {
888
                        activeFilters[active]();
889
                    }
890
                }
891
                table.draw();
892
            });
893
894
            // Clear all filters
895
            $('#clear_search').click(function() {
896
                clearSearch();
897
            });
898
899
        });
900
    </script>
901
[% END %]
902
898
[% INCLUDE 'intranet-bottom.inc' %]
903
[% INCLUDE 'intranet-bottom.inc' %]
899
- 

Return to bug 20600