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

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt (-569 / +572 lines)
Lines 1-3 Link Here
1
[% SET footerjs = 1 %]
1
<!DOCTYPE html>
2
<!DOCTYPE html>
2
[% IF (AllowOfflineCirculation) %]
3
[% IF (AllowOfflineCirculation) %]
3
[% SET manifestattr = 'manifest="/cgi-bin/koha/circ/offline-mf.pl"' %]
4
[% SET manifestattr = 'manifest="/cgi-bin/koha/circ/offline-mf.pl"' %]
Lines 9-584 Link Here
9
<head>
10
<head>
10
<title>Koha &rsaquo; Circulation</title>
11
<title>Koha &rsaquo; Circulation</title>
11
[% INCLUDE 'doc-head-close.inc' %]
12
[% INCLUDE 'doc-head-close.inc' %]
12
[% INCLUDE 'calendar.inc' %]
13
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.indexeddb.js"></script>
14
<script type="text/javascript" src="[% interface %]/[% theme %]/js/offlinecirc.js"></script>
15
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery-ui-timepicker-addon.min.js"></script>
16
[% INCLUDE 'timepicker.inc' %]
17
<script type="text/javascript">
18
//<![CDATA[
19
var ALERT_SUCCESSFUL_CHECKIN = _("Checked in item.");
20
var ALERT_MATERIALS = _("Note about the accompanying materials: %s");
21
var ALERT_RESTRICTED = _("Patron is RESTRICTED");
22
var ALERT_NO_MATCHING_ITEM = _("No item with barcode in offline database (transaction recorded anyway): %s");
23
var ALERT_NOT_CHECKED_OUT = _("Item not listed as checked out in offline database (transaction recorded anyway)");
24
var ALERT_ITEM_WITHDRAWN = _("Item has been withdrawn (transaction recorded anyway)");
25
var ALERT_ITEM_RESTRICTED = _("Item is restricted (transaction recorded anyway)");
26
var ALERT_ITEM_LOST = _("Item has been lost (transaction recorded anyway)");
27
var ALERT_NO_MATCHING_PATRON = _("No patron cardnumber in offline database (proceeding anyway): %s");
28
var ALERT_PATRON_GONE_NO_ADDRESS = _("Patron's address is in doubt (proceeding anyway)");
29
var ALERT_PATRON_CARD_LOST = _("Patron's card is lost");
30
var ALERT_PATRON_EXPIRED = _("Patron's card is expired (%s)");
31
var ALERT_PATRON_BLOCKED_TEMPORARY = _("Patron has had overdue items and is restricted until: %s");
32
var ALERT_PATRON_RESTRICTED = _("Patron is restricted");
33
var ALERT_PATRON_FINE = _("Patron has outstanding fines: %s");
34
var ALERT_PATRON_FINE_OVER_LIMIT = _("Patron fines are over limit: %s");
35
var UPLOAD_PENDING_MESSAGE = _("You have transactions in the offline circulation database on this computer that have not been uploaded.");
36
var NO_UPLOAD_PENDING_MESSAGE = _("You do not have any pending transactions in the offline circulation database on this computer.");
37
38
var start;
39
40
var dateformat = '[% IF ( dateformat_us ) %]mm/dd/yy[% ELSIF ( dateformat_metric ) %]dd/mm/yy[% ELSE %]yy-mm-dd[% END %]';
41
42
function checkin(barcode, item, error) {
43
    var alerts = checkAlerts(barcode, item);
44
    if (typeof item === 'undefined') {
45
        item = { };
46
    }
47
    item.title = item.title || _("(Unknown)");
48
    item.author = item.author || _("(Unknown)");
49
    item.homebranch = item.homebranch || "";
50
    item.holdingbranch = item.holdingbranch || "";
51
    item.callnumber = item.callnumber || "";
52
    item.itemtype = item.itemtype || "";
53
    item.barcode = item.barcode || barcode;
54
    var trans = { "timestamp" : new Date().toMySQLString(),
55
                  "barcode" : barcode,
56
                  "action" : "return"
57
                };
58
    $('#alerts').empty();
59
    $('.offline-home').hide();
60
    $('.offline-sync').hide();
61
    $('.offline-circulation').hide();
62
    $('.offline-circulation-instructions').hide();
63
    $('.offline-returns').show();
64
    kohadb.recordTransaction(trans, function () {
65
        $('#session-returned').show();
66
        $('#already-checked-in tbody').prepend('<tr><td>' + item.title + '</td><td>' + item.author + '</td><td>' + barcode + '</td><td>' + item.homebranch + '</td><td>' + item.holdingbranch + '</td><td></td><td>' + item.callnumber + '</td><td>' + item.itemtype + '</td></tr>');
67
        if (alerts.length > 0) {
68
            $('#alerts').append('<div class="dialog alert"><h3>' + _("Check in message") + '</h3></div>');
69
            for (var msg in alerts) {
70
                $('#alerts .dialog').append('<p>' + alerts[msg] + '</p');
71
            }
72
        } else {
73
            $('#alerts').append('<div class="dialog"><h3>' + ALERT_SUCCESSFUL_CHECKIN + '</h3></div>');
74
        }
75
    });
76
    setTimeout(function() { $('#checkin-barcode').trigger('focus'), 1 });
77
}
78
79
function checkAlerts(barcode, item) {
80
    var alerts = [];
81
    if (typeof item === 'undefined') {
82
        alerts.push(ALERT_NO_MATCHING_ITEM.format(barcode));
83
    } else {
84
        if (typeof item.materials !== 'undefined' && item.materials != null) {
85
            alerts.push(ALERT_MATERIALS.format(item.materials));
86
        }
87
    }
88
    return alerts;
89
}
90
91
function showSyncInfo() {
92
    kohadb.loadSetting("item-timestamp", showTimestamp);
93
    kohadb.loadSetting("patron-timestamp", showTimestamp);
94
    kohadb.loadSetting("issue-timestamp", showTimestamp);
95
    kohadb.loadSetting("dirty", function (key, val) {
96
        if (val) {
97
            $('#upload-message').text(UPLOAD_PENDING_MESSAGE);
98
        } else {
99
            $('#upload-message').text(NO_UPLOAD_PENDING_MESSAGE);
100
        }
101
    });
102
}
103
104
function synchronize() {
105
    kohadb.saveSetting("userid", "[% loggedinusername %]");
106
    kohadb.saveSetting("branchcode", "[% LoginBranchcode %]");
107
    showSyncInfo();
108
    [% UNLESS (AllowOfflineCirculation) %]
109
        reloadRecords();
110
    [% END %]
111
    showSyncInfo();
112
    $('#download-records').click(reloadRecords);
113
    $('#upload-transactions').click(function () {
114
        $('.loading-overlay div').text(_("Uploading transactions, please wait..."));
115
        $('.loading-overlay').show();
116
        $.ajax({
117
            type: "GET",
118
            url: "/cgi-bin/koha/offline_circ/service.pl",
119
        }).done(function (data) {
120
            if (data) {
121
                $('.loading-overlay').hide();
122
                alert(_("Please log in to Koha and try again. (Error: '%s')").format(data));
123
            } else {
124
                var uploadIter = $.indexedDB("koha").objectStore("transactions").each(uploadTransaction);
125
                uploadIter.done(function() {
126
                    $.indexedDB("koha").transaction(["transactions"]).then(function(){
127
                    }, function(err, e){
128
                    }, function(transaction){
129
                        transaction.objectStore("transactions").clear();
130
                    });
131
                    $('.loading-overlay').hide();
132
                    kohadb.saveSetting("dirty", false);
133
                    $('#upload-message').text(NO_UPLOAD_PENDING_MESSAGE);
134
                });
135
            }
136
        });
137
    });
138
139
}
140
141
function showTimestamp(key, value) {
142
    if (typeof value !== 'undefined') {
143
        var ts = new Date(value);
144
        $('#' + key).text($.datepicker.formatDate(dateformat, ts) + ' ' + ts.toTimeString());
145
    } else {
146
        $('#' + key).text(_("(never)"));
147
    }
148
}
149
150
function reloadRecords(ev) {
151
    $(".loading-overlay div").text(_("Loading records, please wait..."));
152
    $(".loading-overlay").show();
153
    start = new Date();
154
    $.indexedDB("koha").transaction(["patrons", "items", "issues"]).then(function(){
155
        loadRecords(0);
156
    }, function(err, e){
157
    }, function(transaction){
158
        transaction.objectStore("patrons").clear();
159
        transaction.objectStore("items").clear();
160
        transaction.objectStore("issues").clear();
161
    });
162
    if (typeof ev !== 'undefined') {
163
        ev.stopPropagation();
164
    }
165
}
166
167
function uploadTransaction(transaction) {
168
    $.ajax({
169
        type: "POST",
170
        url: "/cgi-bin/koha/offline_circ/service.pl",
171
        data: { "userid" : kohadb.settings.userid,
172
                "branchcode" : kohadb.settings.branchcode,
173
                "timestamp" : transaction.value.timestamp,
174
                "action" : transaction.value.action,
175
                "barcode" : transaction.value.barcode,
176
                "cardnumber" : transaction.value.cardnumber,
177
                "amount" : transaction.value.amount,
178
                "pending" : true,
179
              },
180
    });
181
    return undefined, true;
182
}
183
184
function finishedLoading() {
185
    kohadb.saveSetting('item-timestamp', start.toISOString())
186
    kohadb.saveSetting('patron-timestamp', start.toISOString())
187
    kohadb.saveSetting('issue-timestamp', start.toISOString())
188
    showTimestamp('item-timestamp', start.toISOString());
189
    showTimestamp('patron-timestamp', start.toISOString());
190
    showTimestamp('issue-timestamp', start.toISOString());
191
    $(".loading-overlay").hide();
192
}
193
194
function loadRecords(page) {
195
[% IF (AllowOfflineCirculation) %]
196
    $(".loading-overlay div").text(_("Loading page %s, please wait...").format(page));
197
    $(".loading-overlay").show();
198
    $.ajax({
199
        type: "GET",
200
        url: "/cgi-bin/koha/offline_circ/download.pl",
201
        data: { "data": "all",
202
                "page": page
203
              },
204
        dataType: "json",
205
    }).done(function (data) {
206
        $.indexedDB("koha").transaction(["patrons", "items", "issues"]).then(function(){
207
            if (data.finished) {
208
                finishedLoading();
209
            } else {
210
                setTimeout(function () { loadRecords(page + 1); }, 200);
211
            }
212
        }, function(err, e){
213
        }, function(transaction){
214
            if (data.patrons) {
215
                var patrons = transaction.objectStore("patrons");
216
                $.each(data.patrons, function () {
217
                    patrons.put(this);
218
                });
219
            }
220
            if (data.items) {
221
                var items = transaction.objectStore("items");
222
                $.each(data.items, function () {
223
                    items.put(this);
224
                });
225
            }
226
            if (data.issues) {
227
                var issues = transaction.objectStore("issues");
228
                $.each(data.issues, function () {
229
                    issues.put(this);
230
                });
231
            }
232
        });
233
    });
234
[% END %]
235
}
236
237
function validate1(date) {
238
    var today = new Date();
239
    if ( date < today ) {
240
        return true;
241
     } else {
242
        return false;
243
     }
244
};
245
246
function loadPatron(barcode) {
247
    $('#oldissues').hide();
248
    $('#session-issues').hide();
249
    $('#issuest tbody').empty();
250
    $('#session-payments').hide();
251
    $('.checkout-count').text(0);
252
    $.indexedDB("koha").transaction(["patrons", "issues"]).then(function() {
253
    }, function(err, e){
254
    }, function(transaction){
255
        var patrons = transaction.objectStore("patrons");
256
        patrons.get(barcode).done(function (patron, error) {
257
            showPatron(barcode, patron, error);
258
        });
259
        var issuesidx = transaction.objectStore("issues").index("cardnumber");
260
        $('#oldissuest tbody').empty();
261
        issuesidx.each(function (item) {
262
            $('#oldissues').show();
263
            $('#oldissuest tbody').append("<tr><td>" + item.value.date_due + "</td><td>" + item.value.title + "</td><td>" + item.value.barcode + "</td><td>" + item.value.itype + "</td><td>" + item.value.issuedate + "</td><td>" + item.value.issuebranch + "</td><td>" + item.value.callnumber + "</td><td>" + "" + "</td></tr>");
264
            $('.checkout-count').text(parseInt($('.checkout-count').text()) + 1);
265
        }, barcode);
266
    });
267
}
268
269
function checkout(barcode, item, error) {
270
    var alerts = checkAlerts(barcode, item);
271
    if (typeof item === 'undefined') {
272
        item = { };
273
    }
274
    item.title = item.title || "";
275
    item.author = item.author || "";
276
    item.homebranch = item.homebranch || "";
277
    item.holdingbranch = item.holdingbranch || "";
278
    item.callnumber = item.callnumber || "";
279
    item.itemtype = item.itemtype || "";
280
    if ($('#duedatespec').val().length === 0) {
281
        alert(_("You must set a due date in order to use offline circulation!"));
282
        setTimeout(function() { $('#duedatespec').trigger('focus'), 1 });
283
        return;
284
    }
285
    var date_due = new Date($('#duedatespec').datepicker('getDate'));
286
    var trans = { "timestamp" : new Date().toMySQLString(),
287
                  "barcode" : barcode,
288
                  "cardnumber" : curpatron.cardnumber,
289
                  "date_due" : date_due.toMySQLString(),
290
                  "action" : "issue"
291
                };
292
    $('#alerts').empty();
293
    kohadb.recordTransaction(trans, function () {
294
        $('#session-issues').show();
295
        $('#issuest tbody').prepend('<tr><td>' + $.datepicker.formatDate(dateformat, date_due) + date_due.toTimeString() + '</td><td>' + item.title + '</td><td>' + barcode + '</td><td>' + item.itemtype + '</td><td>' + $.datepicker.formatDate(dateformat, new Date()) + '</td><td>' + kohadb.settings.branchcode + '</td><td>' + item.callnumber + '</td><td></td></tr>');
296
        $('.checkout-count').text(parseInt($('.checkout-count').text()) + 1);
297
        if (alerts.length > 0) {
298
            $('#alerts').append('<div class="dialog alert"><h3>' + _("Check out message") + '</h3></div>');
299
            for (var msg in alerts) {
300
                $('#alerts .dialog').append('<p>' + alerts[msg] + '</p');
301
            }
302
        }
303
        $('#checkout-barcode').val('');
304
    });
305
}
306
307
function recordFine(amount) {
308
    var timestamp = new Date()
309
    var trans = { "timestamp" : timestamp.toMySQLString(),
310
                  "cardnumber" : curpatron.cardnumber,
311
                  "amount" : amount,
312
                  "action" : "payment",
313
                };
314
    kohadb.recordTransaction(trans, function () {
315
        $('#session-payments').show();
316
        $('#session-payments tbody').prepend('<tr><td>' + amount + '</td><td>' + $.datepicker.formatDate(dateformat, timestamp) + timestamp.toTimeString() + '</td></tr>');
317
        $('.fine-amount').text(parseInt($('.fine-amount').text()) - amount);
318
    });
319
}
320
321
function checkPatronAlerts(cardnumber, patron) {
322
    var alerts = [];
323
    if (typeof patron === 'undefined') {
324
        alerts.push(ALERT_NO_MATCHING_PATRON.format(cardnumber));
325
    } else {
326
        if (patron.gonenoaddress !== '0') {
327
            alerts.push(ALERT_PATRON_GONE_NO_ADDRESS);
328
        }
329
        if (patron.lost !== '0') {
330
            alerts.push(ALERT_PATRON_CARD_LOST);
331
        }
332
        if (patron.debarred !== null) {
333
            if (patron.debarred != '9999-12-31') {
334
                alerts.push(ALERT_PATRON_BLOCKED_TEMPORARY.format($.datepicker.formatDate(dateformat, new Date(patron.debarred))));
335
            } else {
336
                alerts.push(ALERT_PATRON_RESTRICTED);
337
            }
338
        }
339
        if (new Date(patron.dateexpiry) < new Date()) {
340
            alerts.push(ALERT_PATRON_EXPIRED.format($.datepicker.formatDate(dateformat, new Date(patron.dateexpiry))));
341
        }
342
        if (parseInt(patron.fine) > [% maxoutstanding %]) {
343
            alerts.push(ALERT_PATRON_FINE_OVER_LIMIT.format(patron.fine));
344
        } else if (parseInt(patron.fine) > 0) {
345
            alerts.push(ALERT_PATRON_FINE.format(patron.fine));
346
        }
347
    }
348
    return alerts;
349
}
350
351
var curpatron;
352
353
function showPatron(barcode, patron, error) {
354
    var alerts = checkPatronAlerts(barcode, patron);
355
    if (typeof patron === 'undefined') {
356
        patron = { };
357
    }
358
    patron.surname = patron.surname || "";
359
    patron.firstname = patron.firstname || "";
360
    patron.othernames = patron.othernames || "";
361
    patron.address = patron.address || "";
362
    patron.address2 = patron.address2 || "";
363
    patron.city = patron.city || "";
364
    patron.state = patron.state || "";
365
    patron.country = patron.country || "";
366
    patron.zipcode = patron.zipcode || "";
367
    patron.phone = patron.phone || "";
368
    patron.mobile = patron.mobile || "";
369
    patron.phonepro = patron.phonepro || "";
370
    patron.email = patron.email || "";
371
    patron.emailpro = patron.emailpro || "";
372
    patron.categorycode = patron.categorycode || "";
373
    patron.branchcode = patron.branchcode || "";
374
    patron.cardnumber = barcode;
375
    patron.fine = patron.fine || "0";
376
377
    patron.name = patron.firstname + (patron.othernames.length > 0 ? " (" + patron.othernames + ") " : " ") + patron.surname + " (" + barcode + ")";
378
    if (patron.name.length > 0) {
379
        $('.patron-title').text(patron.name);
380
    } else {
381
        $('.patron-title').text(_("Unrecognized patron (%s)").format(barcode));
382
    }
383
    if (patron.address.length > 0 || patron.address2.length > 0) {
384
        $('#patron-address-1').text(patron.address);
385
        $('#patron-address-2').text(patron.address2);
386
    } else {
387
        $('#patron-address-1').html('<span class="empty" id="noaddressstored">' + _("No address stored.") + '</span></li>');
388
        $('#patron-address-2').text('');
389
    }
390
    if (patron.city.length > 0) {
391
        $('#patron-address-parts').text(patron.city + (patron.state.length > 0 ? ", " + patron.state : "") + " " + patron.zipcode + (patron.country.length > 0 ? ", " + patron.country : ""));
392
    } else {
393
        $('#patron-address-parts').html('<span class="empty" id="nocitystored">' + _("No city stored.") + '</span></li>');
394
    }
395
    if (patron.phone.length > 0 || patron.mobile.length > 0 || patron.phonepro.length > 0) {
396
        $('#patron-phone').text((patron.phone.length > 0 ? patron.phone : (patron.mobile.length > 0 ? patron.mobile : (patron.phonepro.length > 0 ? patron.phonepro : ''))));
397
    } else {
398
        $('#patron-phone').html('<span class="empty" id="nophonestored">' + _("No phone stored.") + '</span></li>');
399
    }
400
    if (patron.email.length > 0 || patron.emailpro.length > 0) {
401
        $('#patron-email').text((patron.email.length > 0 ? patron.email : (patron.emailpro.length > 0 ? patron.emailpro : "")));
402
    } else {
403
        $('#patron-email').html('<span class="empty" id="noemailstored">' + _("No email stored.") + '</span></li>');
404
    }
405
    if (patron.categorycode.length > 0) {
406
        $('#patron-category').text(_("Category: %s").format(patron.categorycode));
407
    } else {
408
        $('#patron-category').html('<span class="empty" id="unknowncategory">' + _("Category code unknown.") + '</span></li>');
409
    }
410
    if (patron.branchcode.length > 0) {
411
        $('#patron-library').text(_("Home library: %s").format(patron.branchcode));
412
    } else {
413
        $('#patron-library').html('<span class="empty" id="unknowncategory">' + _("Home library unknown.") + '</span></li>');
414
    }
415
    $('.fine-amount').text(patron.fine);
416
    $('#alerts').empty();
417
    if (alerts.length > 0) {
418
        $('#alerts').append('<div class="dialog alert"><h3>' + _("Check out message") + '</h3></div>');
419
        for (var msg in alerts) {
420
            $('#alerts .dialog').append('<p>' + alerts[msg] + '</p>');
421
        }
422
    }
423
    curpatron = patron;
424
    $('#yui-main').show();
425
    setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 });
426
}
427
428
// This next bit of code is to deal with the updated session issue
429
window.addEventListener('load', function(e) {
430
    window.applicationCache.addEventListener('updateready', function(e) {
431
        if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
432
            // Browser downloaded a new app cache.
433
            // Swap it in and reload the page to get the new hotness.
434
            window.applicationCache.swapCache();
435
            if (confirm(_("A new version of this site is available. Load it?"))) {
436
                window.location.reload();
437
            }
438
        } else {
439
        // Manifest didn't changed. Nothing new to server.
440
        }
441
    }, false);
442
}, false);
443
444
445
$(document).ready(function () {
446
    kohadb.initialize();
447
    $('#header_search #circ_search .tip').text(_("Enter patron card number:"));
448
449
    $('ul[aria-labelledby="drop3"]').html('<li><a class="toplinks">You cannot change your branch or logout while using offline circulation</a></li>');
450
451
    // Returns code
452
    $('#checkin-form, #checkin_search form').submit(function (event) {
453
        event.preventDefault();
454
        var barcode = $('input[name="barcode"]', this).val();
455
        $('input[name="barcode"]', this).val('');
456
        $.indexedDB("koha").transaction(["items"]).then(function() {
457
        }, function(err, e){
458
        }, function(transaction){
459
            var items = transaction.objectStore("items");
460
            items.get(barcode).done(function (item, error) {
461
                checkin(barcode, item, error);
462
            });
463
        });
464
    });
465
466
    $('#go-to-home').click(function () {
467
        $('#alerts').empty();
468
        $('.offline-sync').hide();
469
        $('.offline-circulation').hide();
470
        $('.offline-returns').hide();
471
        $('.offline-circulation-instructions').hide();
472
        $('.offline-home').show();
473
    });
474
475
    $('#go-to-returns').click(function () {
476
        $('#alerts').empty();
477
        $('.offline-home').hide();
478
        $('.offline-sync').hide();
479
        $('.offline-circulation').hide();
480
        $('.offline-circulation-instructions').hide();
481
        $('.offline-returns').show();
482
        setTimeout(function() { $('#checkin-form input[name="barcode"]').trigger('focus'), 1 });
483
    });
484
485
    $('#go-to-circ').click(function () {
486
        $('#alerts').empty();
487
        $('.offline-home').hide();
488
        $('.offline-sync').hide();
489
        $('.offline-returns').hide();
490
        $('.offline-circulation').hide();
491
        $('.offline-circulation-instructions').show();
492
        $('#header_search').tabs("option", "active", 0);
493
        setTimeout(function() { $('#circ_search input[name="findborrower"]').trigger('focus'), 1 });
494
    });
495
496
    $('#go-to-sync').click(function () {
497
        $('#alerts').empty();
498
        showSyncInfo();
499
        $.ajax({
500
            type: "GET",
501
            url: "/cgi-bin/koha/offline_circ/list.pl",
502
            success: function () {
503
                $('.offline-home').hide();
504
                $('.offline-returns').hide();
505
                $('.offline-circulation').hide();
506
                $('.offline-circulation-instructions').hide();
507
                $('.offline-sync').show();
508
                synchronize();
509
            },
510
            error: function () {
511
                alert(_("You are offline and therefore cannot sync your database"));
512
            }
513
        });
514
    });
515
516
    $('#go-to-pending').click(function (ev) {
517
        $('#alerts').empty();
518
        ev.preventDefault();
519
        $.ajax({
520
            type: "GET",
521
            url: "/cgi-bin/koha/offline_circ/list.pl",
522
            success: function () {
523
                window.location = '/cgi-bin/koha/offline_circ/list.pl';
524
            },
525
            error: function () {
526
                alert(_("You are offline and therefore cannot process pending operations"));
527
            }
528
        });
529
    });
530
531
    $('#patronsearch').submit(function (event) {
532
        event.preventDefault();
533
        loadPatron($('#findborrower').val());
534
        $('.offline-home').hide();
535
        $('.offline-returns').hide();
536
        $('.offline-sync').hide();
537
        $('.offline-circulation-instructions').hide();
538
        $('.offline-circulation').show();
539
        $('#findborrower').val('');
540
        setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 });
541
    });
542
543
    $('#pay-fine').click(function (event) {
544
        event.preventDefault();
545
        recordFine($('#pay-fine-amount').val());
546
    });
547
548
    $('#patronlists').tabs();
549
550
    $("#newduedate").datetimepicker({
551
        minDate: 1, // require that renewal date is after today
552
        hour: 23,
553
        minute: 59
554
    });
555
    $("#duedatespec").datetimepicker({
556
        onClose: function(dateText, inst) {
557
            if (validate_date(dateText, inst) ) {
558
                setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 });
559
            }
560
        },
561
        hour: 23,
562
        minute: 59
563
    }).on("change", function(e, value) {
564
        if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");}
565
    });
566
    $('#mainform').submit(function (event) {
567
        event.preventDefault();
568
        var barcode = $('#checkout-barcode').val();
569
        $.indexedDB("koha").transaction(["items"]).then(function() {
570
        }, function(err, e){
571
        }, function(transaction){
572
            var items = transaction.objectStore("items");
573
            items.get(barcode).done(function (item, error) {
574
                checkout(barcode, item, error);
575
            });
576
        });
577
    });
578
});
579
//]]>
580
</script>
581
</head>
13
</head>
14
582
<body id="circ_offline" class="circ">
15
<body id="circ_offline" class="circ">
583
[% INCLUDE 'header.inc' %]
16
[% INCLUDE 'header.inc' %]
584
[% INCLUDE 'circ-search.inc' %]
17
[% INCLUDE 'circ-search.inc' %]
Lines 781-784 $(document).ready(function () { Link Here
781
    </div>
214
    </div>
782
</div>
215
</div>
783
216
217
[% MACRO jsinclude BLOCK %]
218
    [% INCLUDE 'calendar.inc' %]
219
    <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.indexeddb.js"></script>
220
    <script type="text/javascript" src="[% interface %]/[% theme %]/js/offlinecirc.js"></script>
221
    <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery-ui-timepicker-addon.min.js"></script>
222
    [% INCLUDE 'timepicker.inc' %]
223
    <script type="text/javascript">
224
        var ALERT_SUCCESSFUL_CHECKIN = _("Checked in item.");
225
        var ALERT_MATERIALS = _("Note about the accompanying materials: %s");
226
        var ALERT_RESTRICTED = _("Patron is RESTRICTED");
227
        var ALERT_NO_MATCHING_ITEM = _("No item with barcode in offline database (transaction recorded anyway): %s");
228
        var ALERT_NOT_CHECKED_OUT = _("Item not listed as checked out in offline database (transaction recorded anyway)");
229
        var ALERT_ITEM_WITHDRAWN = _("Item has been withdrawn (transaction recorded anyway)");
230
        var ALERT_ITEM_RESTRICTED = _("Item is restricted (transaction recorded anyway)");
231
        var ALERT_ITEM_LOST = _("Item has been lost (transaction recorded anyway)");
232
        var ALERT_NO_MATCHING_PATRON = _("No patron cardnumber in offline database (proceeding anyway): %s");
233
        var ALERT_PATRON_GONE_NO_ADDRESS = _("Patron's address is in doubt (proceeding anyway)");
234
        var ALERT_PATRON_CARD_LOST = _("Patron's card is lost");
235
        var ALERT_PATRON_EXPIRED = _("Patron's card is expired (%s)");
236
        var ALERT_PATRON_BLOCKED_TEMPORARY = _("Patron has had overdue items and is restricted until: %s");
237
        var ALERT_PATRON_RESTRICTED = _("Patron is restricted");
238
        var ALERT_PATRON_FINE = _("Patron has outstanding fines: %s");
239
        var ALERT_PATRON_FINE_OVER_LIMIT = _("Patron fines are over limit: %s");
240
        var UPLOAD_PENDING_MESSAGE = _("You have transactions in the offline circulation database on this computer that have not been uploaded.");
241
        var NO_UPLOAD_PENDING_MESSAGE = _("You do not have any pending transactions in the offline circulation database on this computer.");
242
243
        var start;
244
245
        var dateformat = '[% IF ( dateformat_us ) %]mm/dd/yy[% ELSIF ( dateformat_metric ) %]dd/mm/yy[% ELSE %]yy-mm-dd[% END %]';
246
247
        function checkin(barcode, item, error) {
248
            var alerts = checkAlerts(barcode, item);
249
            if (typeof item === 'undefined') {
250
                item = { };
251
            }
252
            item.title = item.title || _("(Unknown)");
253
            item.author = item.author || _("(Unknown)");
254
            item.homebranch = item.homebranch || "";
255
            item.holdingbranch = item.holdingbranch || "";
256
            item.callnumber = item.callnumber || "";
257
            item.itemtype = item.itemtype || "";
258
            item.barcode = item.barcode || barcode;
259
            var trans = { "timestamp" : new Date().toMySQLString(),
260
                          "barcode" : barcode,
261
                          "action" : "return"
262
                        };
263
            $('#alerts').empty();
264
            $('.offline-home').hide();
265
            $('.offline-sync').hide();
266
            $('.offline-circulation').hide();
267
            $('.offline-circulation-instructions').hide();
268
            $('.offline-returns').show();
269
            kohadb.recordTransaction(trans, function () {
270
                $('#session-returned').show();
271
                $('#already-checked-in tbody').prepend('<tr><td>' + item.title + '</td><td>' + item.author + '</td><td>' + barcode + '</td><td>' + item.homebranch + '</td><td>' + item.holdingbranch + '</td><td></td><td>' + item.callnumber + '</td><td>' + item.itemtype + '</td></tr>');
272
                if (alerts.length > 0) {
273
                    $('#alerts').append('<div class="dialog alert"><h3>' + _("Check in message") + '</h3></div>');
274
                    for (var msg in alerts) {
275
                        $('#alerts .dialog').append('<p>' + alerts[msg] + '</p');
276
                    }
277
                } else {
278
                    $('#alerts').append('<div class="dialog"><h3>' + ALERT_SUCCESSFUL_CHECKIN + '</h3></div>');
279
                }
280
            });
281
            setTimeout(function() { $('#checkin-barcode').trigger('focus'), 1 });
282
        }
283
284
        function checkAlerts(barcode, item) {
285
            var alerts = [];
286
            if (typeof item === 'undefined') {
287
                alerts.push(ALERT_NO_MATCHING_ITEM.format(barcode));
288
            } else {
289
                if (typeof item.materials !== 'undefined' && item.materials != null) {
290
                    alerts.push(ALERT_MATERIALS.format(item.materials));
291
                }
292
            }
293
            return alerts;
294
        }
295
296
        function showSyncInfo() {
297
            kohadb.loadSetting("item-timestamp", showTimestamp);
298
            kohadb.loadSetting("patron-timestamp", showTimestamp);
299
            kohadb.loadSetting("issue-timestamp", showTimestamp);
300
            kohadb.loadSetting("dirty", function (key, val) {
301
                if (val) {
302
                    $('#upload-message').text(UPLOAD_PENDING_MESSAGE);
303
                } else {
304
                    $('#upload-message').text(NO_UPLOAD_PENDING_MESSAGE);
305
                }
306
            });
307
        }
308
309
        function synchronize() {
310
            kohadb.saveSetting("userid", "[% loggedinusername %]");
311
            kohadb.saveSetting("branchcode", "[% LoginBranchcode %]");
312
            showSyncInfo();
313
            [% UNLESS (AllowOfflineCirculation) %]
314
                reloadRecords();
315
            [% END %]
316
            showSyncInfo();
317
            $('#download-records').click(reloadRecords);
318
            $('#upload-transactions').click(function () {
319
                $('.loading-overlay div').text(_("Uploading transactions, please wait..."));
320
                $('.loading-overlay').show();
321
                $.ajax({
322
                    type: "GET",
323
                    url: "/cgi-bin/koha/offline_circ/service.pl",
324
                }).done(function (data) {
325
                    if (data) {
326
                        $('.loading-overlay').hide();
327
                        alert(_("Please log in to Koha and try again. (Error: '%s')").format(data));
328
                    } else {
329
                        var uploadIter = $.indexedDB("koha").objectStore("transactions").each(uploadTransaction);
330
                        uploadIter.done(function() {
331
                            $.indexedDB("koha").transaction(["transactions"]).then(function(){
332
                            }, function(err, e){
333
                            }, function(transaction){
334
                                transaction.objectStore("transactions").clear();
335
                            });
336
                            $('.loading-overlay').hide();
337
                            kohadb.saveSetting("dirty", false);
338
                            $('#upload-message').text(NO_UPLOAD_PENDING_MESSAGE);
339
                        });
340
                    }
341
                });
342
            });
343
344
        }
345
346
        function showTimestamp(key, value) {
347
            if (typeof value !== 'undefined') {
348
                var ts = new Date(value);
349
                $('#' + key).text($.datepicker.formatDate(dateformat, ts) + ' ' + ts.toTimeString());
350
            } else {
351
                $('#' + key).text(_("(never)"));
352
            }
353
        }
354
355
        function reloadRecords(ev) {
356
            $(".loading-overlay div").text(_("Loading records, please wait..."));
357
            $(".loading-overlay").show();
358
            start = new Date();
359
            $.indexedDB("koha").transaction(["patrons", "items", "issues"]).then(function(){
360
                loadRecords(0);
361
            }, function(err, e){
362
            }, function(transaction){
363
                transaction.objectStore("patrons").clear();
364
                transaction.objectStore("items").clear();
365
                transaction.objectStore("issues").clear();
366
            });
367
            if (typeof ev !== 'undefined') {
368
                ev.stopPropagation();
369
            }
370
        }
371
372
        function uploadTransaction(transaction) {
373
            $.ajax({
374
                type: "POST",
375
                url: "/cgi-bin/koha/offline_circ/service.pl",
376
                data: { "userid" : kohadb.settings.userid,
377
                        "branchcode" : kohadb.settings.branchcode,
378
                        "timestamp" : transaction.value.timestamp,
379
                        "action" : transaction.value.action,
380
                        "barcode" : transaction.value.barcode,
381
                        "cardnumber" : transaction.value.cardnumber,
382
                        "amount" : transaction.value.amount,
383
                        "pending" : true,
384
                      },
385
            });
386
            return undefined, true;
387
        }
388
389
        function finishedLoading() {
390
            kohadb.saveSetting('item-timestamp', start.toISOString())
391
            kohadb.saveSetting('patron-timestamp', start.toISOString())
392
            kohadb.saveSetting('issue-timestamp', start.toISOString())
393
            showTimestamp('item-timestamp', start.toISOString());
394
            showTimestamp('patron-timestamp', start.toISOString());
395
            showTimestamp('issue-timestamp', start.toISOString());
396
            $(".loading-overlay").hide();
397
        }
398
399
        function loadRecords(page) {
400
        [% IF (AllowOfflineCirculation) %]
401
            $(".loading-overlay div").text(_("Loading page %s, please wait...").format(page));
402
            $(".loading-overlay").show();
403
            $.ajax({
404
                type: "GET",
405
                url: "/cgi-bin/koha/offline_circ/download.pl",
406
                data: { "data": "all",
407
                        "page": page
408
                      },
409
                dataType: "json",
410
            }).done(function (data) {
411
                $.indexedDB("koha").transaction(["patrons", "items", "issues"]).then(function(){
412
                    if (data.finished) {
413
                        finishedLoading();
414
                    } else {
415
                        setTimeout(function () { loadRecords(page + 1); }, 200);
416
                    }
417
                }, function(err, e){
418
                }, function(transaction){
419
                    if (data.patrons) {
420
                        var patrons = transaction.objectStore("patrons");
421
                        $.each(data.patrons, function () {
422
                            patrons.put(this);
423
                        });
424
                    }
425
                    if (data.items) {
426
                        var items = transaction.objectStore("items");
427
                        $.each(data.items, function () {
428
                            items.put(this);
429
                        });
430
                    }
431
                    if (data.issues) {
432
                        var issues = transaction.objectStore("issues");
433
                        $.each(data.issues, function () {
434
                            issues.put(this);
435
                        });
436
                    }
437
                });
438
            });
439
        [% END %]
440
        }
441
442
        function validate1(date) {
443
            var today = new Date();
444
            if ( date < today ) {
445
                return true;
446
             } else {
447
                return false;
448
             }
449
        };
450
451
        function loadPatron(barcode) {
452
            $('#oldissues').hide();
453
            $('#session-issues').hide();
454
            $('#issuest tbody').empty();
455
            $('#session-payments').hide();
456
            $('.checkout-count').text(0);
457
            $.indexedDB("koha").transaction(["patrons", "issues"]).then(function() {
458
            }, function(err, e){
459
            }, function(transaction){
460
                var patrons = transaction.objectStore("patrons");
461
                patrons.get(barcode).done(function (patron, error) {
462
                    showPatron(barcode, patron, error);
463
                });
464
                var issuesidx = transaction.objectStore("issues").index("cardnumber");
465
                $('#oldissuest tbody').empty();
466
                issuesidx.each(function (item) {
467
                    $('#oldissues').show();
468
                    $('#oldissuest tbody').append("<tr><td>" + item.value.date_due + "</td><td>" + item.value.title + "</td><td>" + item.value.barcode + "</td><td>" + item.value.itype + "</td><td>" + item.value.issuedate + "</td><td>" + item.value.issuebranch + "</td><td>" + item.value.callnumber + "</td><td>" + "" + "</td></tr>");
469
                    $('.checkout-count').text(parseInt($('.checkout-count').text()) + 1);
470
                }, barcode);
471
            });
472
        }
473
474
        function checkout(barcode, item, error) {
475
            var alerts = checkAlerts(barcode, item);
476
            if (typeof item === 'undefined') {
477
                item = { };
478
            }
479
            item.title = item.title || "";
480
            item.author = item.author || "";
481
            item.homebranch = item.homebranch || "";
482
            item.holdingbranch = item.holdingbranch || "";
483
            item.callnumber = item.callnumber || "";
484
            item.itemtype = item.itemtype || "";
485
            if ($('#duedatespec').val().length === 0) {
486
                alert(_("You must set a due date in order to use offline circulation!"));
487
                setTimeout(function() { $('#duedatespec').trigger('focus'), 1 });
488
                return;
489
            }
490
            var date_due = new Date($('#duedatespec').datepicker('getDate'));
491
            var trans = { "timestamp" : new Date().toMySQLString(),
492
                          "barcode" : barcode,
493
                          "cardnumber" : curpatron.cardnumber,
494
                          "date_due" : date_due.toMySQLString(),
495
                          "action" : "issue"
496
                        };
497
            $('#alerts').empty();
498
            kohadb.recordTransaction(trans, function () {
499
                $('#session-issues').show();
500
                $('#issuest tbody').prepend('<tr><td>' + $.datepicker.formatDate(dateformat, date_due) + date_due.toTimeString() + '</td><td>' + item.title + '</td><td>' + barcode + '</td><td>' + item.itemtype + '</td><td>' + $.datepicker.formatDate(dateformat, new Date()) + '</td><td>' + kohadb.settings.branchcode + '</td><td>' + item.callnumber + '</td><td></td></tr>');
501
                $('.checkout-count').text(parseInt($('.checkout-count').text()) + 1);
502
                if (alerts.length > 0) {
503
                    $('#alerts').append('<div class="dialog alert"><h3>' + _("Check out message") + '</h3></div>');
504
                    for (var msg in alerts) {
505
                        $('#alerts .dialog').append('<p>' + alerts[msg] + '</p');
506
                    }
507
                }
508
                $('#checkout-barcode').val('');
509
            });
510
        }
511
512
        function recordFine(amount) {
513
            var timestamp = new Date()
514
            var trans = { "timestamp" : timestamp.toMySQLString(),
515
                          "cardnumber" : curpatron.cardnumber,
516
                          "amount" : amount,
517
                          "action" : "payment",
518
                        };
519
            kohadb.recordTransaction(trans, function () {
520
                $('#session-payments').show();
521
                $('#session-payments tbody').prepend('<tr><td>' + amount + '</td><td>' + $.datepicker.formatDate(dateformat, timestamp) + timestamp.toTimeString() + '</td></tr>');
522
                $('.fine-amount').text(parseInt($('.fine-amount').text()) - amount);
523
            });
524
        }
525
526
        function checkPatronAlerts(cardnumber, patron) {
527
            var alerts = [];
528
            if (typeof patron === 'undefined') {
529
                alerts.push(ALERT_NO_MATCHING_PATRON.format(cardnumber));
530
            } else {
531
                if (patron.gonenoaddress !== '0') {
532
                    alerts.push(ALERT_PATRON_GONE_NO_ADDRESS);
533
                }
534
                if (patron.lost !== '0') {
535
                    alerts.push(ALERT_PATRON_CARD_LOST);
536
                }
537
                if (patron.debarred !== null) {
538
                    if (patron.debarred != '9999-12-31') {
539
                        alerts.push(ALERT_PATRON_BLOCKED_TEMPORARY.format($.datepicker.formatDate(dateformat, new Date(patron.debarred))));
540
                    } else {
541
                        alerts.push(ALERT_PATRON_RESTRICTED);
542
                    }
543
                }
544
                if (new Date(patron.dateexpiry) < new Date()) {
545
                    alerts.push(ALERT_PATRON_EXPIRED.format($.datepicker.formatDate(dateformat, new Date(patron.dateexpiry))));
546
                }
547
                if (parseInt(patron.fine) > [% maxoutstanding %]) {
548
                    alerts.push(ALERT_PATRON_FINE_OVER_LIMIT.format(patron.fine));
549
                } else if (parseInt(patron.fine) > 0) {
550
                    alerts.push(ALERT_PATRON_FINE.format(patron.fine));
551
                }
552
            }
553
            return alerts;
554
        }
555
556
        var curpatron;
557
558
        function showPatron(barcode, patron, error) {
559
            var alerts = checkPatronAlerts(barcode, patron);
560
            if (typeof patron === 'undefined') {
561
                patron = { };
562
            }
563
            patron.surname = patron.surname || "";
564
            patron.firstname = patron.firstname || "";
565
            patron.othernames = patron.othernames || "";
566
            patron.address = patron.address || "";
567
            patron.address2 = patron.address2 || "";
568
            patron.city = patron.city || "";
569
            patron.state = patron.state || "";
570
            patron.country = patron.country || "";
571
            patron.zipcode = patron.zipcode || "";
572
            patron.phone = patron.phone || "";
573
            patron.mobile = patron.mobile || "";
574
            patron.phonepro = patron.phonepro || "";
575
            patron.email = patron.email || "";
576
            patron.emailpro = patron.emailpro || "";
577
            patron.categorycode = patron.categorycode || "";
578
            patron.branchcode = patron.branchcode || "";
579
            patron.cardnumber = barcode;
580
            patron.fine = patron.fine || "0";
581
582
            patron.name = patron.firstname + (patron.othernames.length > 0 ? " (" + patron.othernames + ") " : " ") + patron.surname + " (" + barcode + ")";
583
            if (patron.name.length > 0) {
584
                $('.patron-title').text(patron.name);
585
            } else {
586
                $('.patron-title').text(_("Unrecognized patron (%s)").format(barcode));
587
            }
588
            if (patron.address.length > 0 || patron.address2.length > 0) {
589
                $('#patron-address-1').text(patron.address);
590
                $('#patron-address-2').text(patron.address2);
591
            } else {
592
                $('#patron-address-1').html('<span class="empty" id="noaddressstored">' + _("No address stored.") + '</span></li>');
593
                $('#patron-address-2').text('');
594
            }
595
            if (patron.city.length > 0) {
596
                $('#patron-address-parts').text(patron.city + (patron.state.length > 0 ? ", " + patron.state : "") + " " + patron.zipcode + (patron.country.length > 0 ? ", " + patron.country : ""));
597
            } else {
598
                $('#patron-address-parts').html('<span class="empty" id="nocitystored">' + _("No city stored.") + '</span></li>');
599
            }
600
            if (patron.phone.length > 0 || patron.mobile.length > 0 || patron.phonepro.length > 0) {
601
                $('#patron-phone').text((patron.phone.length > 0 ? patron.phone : (patron.mobile.length > 0 ? patron.mobile : (patron.phonepro.length > 0 ? patron.phonepro : ''))));
602
            } else {
603
                $('#patron-phone').html('<span class="empty" id="nophonestored">' + _("No phone stored.") + '</span></li>');
604
            }
605
            if (patron.email.length > 0 || patron.emailpro.length > 0) {
606
                $('#patron-email').text((patron.email.length > 0 ? patron.email : (patron.emailpro.length > 0 ? patron.emailpro : "")));
607
            } else {
608
                $('#patron-email').html('<span class="empty" id="noemailstored">' + _("No email stored.") + '</span></li>');
609
            }
610
            if (patron.categorycode.length > 0) {
611
                $('#patron-category').text(_("Category: %s").format(patron.categorycode));
612
            } else {
613
                $('#patron-category').html('<span class="empty" id="unknowncategory">' + _("Category code unknown.") + '</span></li>');
614
            }
615
            if (patron.branchcode.length > 0) {
616
                $('#patron-library').text(_("Home library: %s").format(patron.branchcode));
617
            } else {
618
                $('#patron-library').html('<span class="empty" id="unknowncategory">' + _("Home library unknown.") + '</span></li>');
619
            }
620
            $('.fine-amount').text(patron.fine);
621
            $('#alerts').empty();
622
            if (alerts.length > 0) {
623
                $('#alerts').append('<div class="dialog alert"><h3>' + _("Check out message") + '</h3></div>');
624
                for (var msg in alerts) {
625
                    $('#alerts .dialog').append('<p>' + alerts[msg] + '</p>');
626
                }
627
            }
628
            curpatron = patron;
629
            $('#yui-main').show();
630
            setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 });
631
        }
632
633
        // This next bit of code is to deal with the updated session issue
634
        window.addEventListener('load', function(e) {
635
            window.applicationCache.addEventListener('updateready', function(e) {
636
                if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
637
                    // Browser downloaded a new app cache.
638
                    // Swap it in and reload the page to get the new hotness.
639
                    window.applicationCache.swapCache();
640
                    if (confirm(_("A new version of this site is available. Load it?"))) {
641
                        window.location.reload();
642
                    }
643
                } else {
644
                // Manifest didn't changed. Nothing new to server.
645
                }
646
            }, false);
647
        }, false);
648
649
650
        $(document).ready(function () {
651
            kohadb.initialize();
652
            $('#header_search #circ_search .tip').text(_("Enter patron card number:"));
653
654
            $('ul[aria-labelledby="drop3"]').html('<li><a class="toplinks">You cannot change your branch or logout while using offline circulation</a></li>');
655
656
            // Returns code
657
            $('#checkin-form, #checkin_search form').submit(function (event) {
658
                event.preventDefault();
659
                var barcode = $('input[name="barcode"]', this).val();
660
                $('input[name="barcode"]', this).val('');
661
                $.indexedDB("koha").transaction(["items"]).then(function() {
662
                }, function(err, e){
663
                }, function(transaction){
664
                    var items = transaction.objectStore("items");
665
                    items.get(barcode).done(function (item, error) {
666
                        checkin(barcode, item, error);
667
                    });
668
                });
669
            });
670
671
            $('#go-to-home').click(function () {
672
                $('#alerts').empty();
673
                $('.offline-sync').hide();
674
                $('.offline-circulation').hide();
675
                $('.offline-returns').hide();
676
                $('.offline-circulation-instructions').hide();
677
                $('.offline-home').show();
678
            });
679
680
            $('#go-to-returns').click(function () {
681
                $('#alerts').empty();
682
                $('.offline-home').hide();
683
                $('.offline-sync').hide();
684
                $('.offline-circulation').hide();
685
                $('.offline-circulation-instructions').hide();
686
                $('.offline-returns').show();
687
                setTimeout(function() { $('#checkin-form input[name="barcode"]').trigger('focus'), 1 });
688
            });
689
690
            $('#go-to-circ').click(function () {
691
                $('#alerts').empty();
692
                $('.offline-home').hide();
693
                $('.offline-sync').hide();
694
                $('.offline-returns').hide();
695
                $('.offline-circulation').hide();
696
                $('.offline-circulation-instructions').show();
697
                $('#header_search').tabs("option", "active", 0);
698
                setTimeout(function() { $('#circ_search input[name="findborrower"]').trigger('focus'), 1 });
699
            });
700
701
            $('#go-to-sync').click(function () {
702
                $('#alerts').empty();
703
                showSyncInfo();
704
                $.ajax({
705
                    type: "GET",
706
                    url: "/cgi-bin/koha/offline_circ/list.pl",
707
                    success: function () {
708
                        $('.offline-home').hide();
709
                        $('.offline-returns').hide();
710
                        $('.offline-circulation').hide();
711
                        $('.offline-circulation-instructions').hide();
712
                        $('.offline-sync').show();
713
                        synchronize();
714
                    },
715
                    error: function () {
716
                        alert(_("You are offline and therefore cannot sync your database"));
717
                    }
718
                });
719
            });
720
721
            $('#go-to-pending').click(function (ev) {
722
                $('#alerts').empty();
723
                ev.preventDefault();
724
                $.ajax({
725
                    type: "GET",
726
                    url: "/cgi-bin/koha/offline_circ/list.pl",
727
                    success: function () {
728
                        window.location = '/cgi-bin/koha/offline_circ/list.pl';
729
                    },
730
                    error: function () {
731
                        alert(_("You are offline and therefore cannot process pending operations"));
732
                    }
733
                });
734
            });
735
736
            $('#patronsearch').submit(function (event) {
737
                event.preventDefault();
738
                loadPatron($('#findborrower').val());
739
                $('.offline-home').hide();
740
                $('.offline-returns').hide();
741
                $('.offline-sync').hide();
742
                $('.offline-circulation-instructions').hide();
743
                $('.offline-circulation').show();
744
                $('#findborrower').val('');
745
                setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 });
746
            });
747
748
            $('#pay-fine').click(function (event) {
749
                event.preventDefault();
750
                recordFine($('#pay-fine-amount').val());
751
            });
752
753
            $('#patronlists').tabs();
754
755
            $("#newduedate").datetimepicker({
756
                minDate: 1, // require that renewal date is after today
757
                hour: 23,
758
                minute: 59
759
            });
760
            $("#duedatespec").datetimepicker({
761
                onClose: function(dateText, inst) {
762
                    if (validate_date(dateText, inst) ) {
763
                        setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 });
764
                    }
765
                },
766
                hour: 23,
767
                minute: 59
768
            }).on("change", function(e, value) {
769
                if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");}
770
            });
771
            $('#mainform').submit(function (event) {
772
                event.preventDefault();
773
                var barcode = $('#checkout-barcode').val();
774
                $.indexedDB("koha").transaction(["items"]).then(function() {
775
                }, function(err, e){
776
                }, function(transaction){
777
                    var items = transaction.objectStore("items");
778
                    items.get(barcode).done(function (item, error) {
779
                        checkout(barcode, item, error);
780
                    });
781
                });
782
            });
783
        });
784
    </script>
785
[% END %]
786
784
[% INCLUDE 'intranet-bottom.inc' %]
787
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/list.tt (-52 / +55 lines)
Lines 1-58 Link Here
1
[% SET footerjs = 1 %]
1
    [% INCLUDE "doc-head-open.inc" %]
2
    [% INCLUDE "doc-head-open.inc" %]
2
    <title>Koha &rsaquo; Circulation &rsaquo; Offline circulation</title>
3
    <title>Koha &rsaquo; Circulation &rsaquo; Offline circulation</title>
3
    [% INCLUDE "doc-head-close.inc" %]
4
    [% INCLUDE "doc-head-close.inc" %]
4
    <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script>
5
    <script type="text/javascript">
6
    //<![CDATA[
7
        $(document).ready(function() {
8
9
        $("span.clearall").html("<a id=\"CheckNone\" href=\"/cgi-bin/koha/offline_circ/list.pl\">"+_("Uncheck all")+"<\/a>");
10
        $("span.checkall").html("<a id=\"CheckAll\" href=\"/cgi-bin/koha/offline_circ/list.pl\">"+_("Check all")+"<\/a>");
11
            $('#CheckNone').click(function() {
12
                $("#operations").unCheckCheckboxes();
13
                return false;
14
            });
15
            $('#CheckAll').click(function() {
16
                $("#operations").checkCheckboxes();
17
                return false;
18
            });
19
            $('#process,#delete').click(function() {
20
                var action = $(this).attr("id");
21
                $(":checkbox[name=operationid]:checked").each(function() {
22
                    var cb = $(this);
23
                    $.ajax({
24
                        url: "process.pl",
25
                        data: { 'action': action, 'operationid': this.value },
26
                        async: false,
27
                        dataType: "text",
28
                        success: function(data) {
29
                            if( data == "Added." ){
30
                                cb.replaceWith(_("Added."));
31
                            } else if ( data == "Deleted."){
32
                                cb.replaceWith(_("Deleted."));
33
                            } else if ( data == "Success."){
34
                                cb.replaceWith(_("Success."));
35
                            } else if ( data == "Item not issued."){
36
                                cb.replaceWith(_("Item not checked out."));
37
                            } else if ( data == "Item not found."){
38
                                cb.replaceWith(_("Item not found."));
39
                            } else if ( data == "Barcode not found."){
40
                                cb.replaceWith(_("Item not found."));
41
                            } else if ( data == "Borrower not found."){
42
                                cb.replaceWith(_("Patron not found."));
43
                            } else {
44
                                cb.replaceWith(data);
45
                            }
46
                        }});
47
                });
48
                if( $('#operations tbody :checkbox').size() == 0 ) {
49
                    $('#actions').hide();
50
                }
51
            });
52
        });
53
    //]]>
54
    </script>
55
</head>
5
</head>
6
56
<body id="ocirc_list" class="circ ocirc">
7
<body id="ocirc_list" class="circ ocirc">
57
    [% INCLUDE 'header.inc' %]
8
    [% INCLUDE 'header.inc' %]
58
    [% INCLUDE 'circ-search.inc' %]
9
    [% INCLUDE 'circ-search.inc' %]
Lines 134-137 Link Here
134
85
135
    </div>
86
    </div>
136
87
137
    [% INCLUDE 'intranet-bottom.inc' %]
88
[% MACRO jsinclude BLOCK %]
89
    <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script>
90
    <script type="text/javascript">
91
        $(document).ready(function() {
92
93
        $("span.clearall").html("<a id=\"CheckNone\" href=\"/cgi-bin/koha/offline_circ/list.pl\">"+_("Uncheck all")+"<\/a>");
94
        $("span.checkall").html("<a id=\"CheckAll\" href=\"/cgi-bin/koha/offline_circ/list.pl\">"+_("Check all")+"<\/a>");
95
            $('#CheckNone').click(function() {
96
                $("#operations").unCheckCheckboxes();
97
                return false;
98
            });
99
            $('#CheckAll').click(function() {
100
                $("#operations").checkCheckboxes();
101
                return false;
102
            });
103
            $('#process,#delete').click(function() {
104
                var action = $(this).attr("id");
105
                $(":checkbox[name=operationid]:checked").each(function() {
106
                    var cb = $(this);
107
                    $.ajax({
108
                        url: "process.pl",
109
                        data: { 'action': action, 'operationid': this.value },
110
                        async: false,
111
                        dataType: "text",
112
                        success: function(data) {
113
                            if( data == "Added." ){
114
                                cb.replaceWith(_("Added."));
115
                            } else if ( data == "Deleted."){
116
                                cb.replaceWith(_("Deleted."));
117
                            } else if ( data == "Success."){
118
                                cb.replaceWith(_("Success."));
119
                            } else if ( data == "Item not issued."){
120
                                cb.replaceWith(_("Item not checked out."));
121
                            } else if ( data == "Item not found."){
122
                                cb.replaceWith(_("Item not found."));
123
                            } else if ( data == "Barcode not found."){
124
                                cb.replaceWith(_("Item not found."));
125
                            } else if ( data == "Borrower not found."){
126
                                cb.replaceWith(_("Patron not found."));
127
                            } else {
128
                                cb.replaceWith(data);
129
                            }
130
                        }});
131
                });
132
                if( $('#operations tbody :checkbox').size() == 0 ) {
133
                    $('#actions').hide();
134
                }
135
            });
136
        });
137
    </script>
138
[% END %]
139
140
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt (-68 / +69 lines)
Lines 1-74 Link Here
1
[% SET footerjs = 1 %]
1
[% INCLUDE 'doc-head-open.inc' %]
2
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Circulation &rsaquo; Offline circulation file upload</title>
3
<title>Koha &rsaquo; Circulation &rsaquo; Offline circulation file upload</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
[% INCLUDE 'doc-head-close.inc' %]
4
5
<script type="text/javascript" src="[% interface %]/[% theme %]/js/background-job-progressbar.js"></script>
6
<script type="text/javascript" src="[% interface %]/[% theme %]/js/file-upload.js"></script>
7
<script type="text/javascript">
8
//<![CDATA[
9
var xhr;
10
$(document).ready(function(){
11
    $("#enqueuefile").hide();
12
    $("#processfile").hide();
13
    $("#upload_file").on("click",function(){
14
        StartUpload();
15
    });
16
    $("#queueformsubmit").on("click",function(){
17
        var processfile = document.getElementById("processfile");
18
        return CheckForm( processfile );
19
    });
20
    $("#mainformsubmit").on("click",function(){
21
        var enqueuefile = document.getElementById("enqueuefile");
22
        return CheckForm( enqueuefile );
23
    });
24
});
25
26
function StartUpload() {
27
    if( $('#fileToUpload').prop('files').length == 0 ) return;
28
    $('#fileuploadform input.submit').prop('disabled',true);
29
    $("#fileuploadfailed").hide();
30
    $("#processfile").hide();
31
    $("#fileuploadstatus").show();
32
    $("form#processfile #uploadedfileid").val('');
33
    $("form#enqueuefile #uploadedfileid").val('');
34
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), 'temp=1', cbUpload );
35
}
36
37
function cbUpload( status, fileid, errors ) {
38
    if( status=='done' ) {
39
        $("form#processfile #uploadedfileid").val( fileid );
40
        $("form#enqueuefile #uploadedfileid").val( fileid );
41
        $('#fileToUpload').prop('disabled',true);
42
        $("#processfile").show();
43
        $("#enqueuefile").show();
44
    } else {
45
        var errMsgs = [ _("Error code 0 not used"), _("File already exists"), _("Directory is not writeable"), _("Root directory for uploads not defined"), _("Temporary directory for uploads not defined") ];
46
        var errCode = errors[$('#fileToUpload').prop('files')[0].name].code;
47
        $("#fileuploadstatus").hide();
48
        $("#fileuploadfailed").show();
49
        $("#fileuploadfailed").text( _("Upload status: ") +
50
            ( status=='failed'? _("Failed") + " - (" + errCode + ") " + errMsgs[errCode]:
51
            ( status=='denied'? _("Denied"): status ))
52
        );
53
    }
54
}
55
56
function CheckForm(f) {
57
    if (f.uploadedfileid.value == '') {
58
        alert(_("Please upload a file first."));
59
    } else {
60
        $("#fileuploadstatus").hide();
61
        $("#fileuploadform").slideUp();
62
        $("#mainformsubmit").prop('disabled',true);
63
        $("#queueformsubmit").prop('disabled',true);
64
        return submitBackgroundJob(f);
65
    }
66
    return false;
67
}
68
69
//]]>
70
</script>
71
</head>
5
</head>
6
72
<body id="ocirc_process_koc" class="circ ocirc">
7
<body id="ocirc_process_koc" class="circ ocirc">
73
[% INCLUDE 'header.inc' %]
8
[% INCLUDE 'header.inc' %]
74
[% INCLUDE 'circ-search.inc' %]
9
[% INCLUDE 'circ-search.inc' %]
Lines 128-131 function CheckForm(f) { Link Here
128
63
129
64
130
</div>
65
</div>
66
67
[% MACRO jsinclude BLOCK %]
68
    <script type="text/javascript" src="[% interface %]/[% theme %]/js/background-job-progressbar.js"></script>
69
    <script type="text/javascript" src="[% interface %]/[% theme %]/js/file-upload.js"></script>
70
    <script type="text/javascript">
71
        var xhr;
72
        $(document).ready(function(){
73
            $("#enqueuefile").hide();
74
            $("#processfile").hide();
75
            $("#upload_file").on("click",function(){
76
                StartUpload();
77
            });
78
            $("#queueformsubmit").on("click",function(){
79
                var processfile = document.getElementById("processfile");
80
                return CheckForm( processfile );
81
            });
82
            $("#mainformsubmit").on("click",function(){
83
                var enqueuefile = document.getElementById("enqueuefile");
84
                return CheckForm( enqueuefile );
85
            });
86
        });
87
88
        function StartUpload() {
89
            if( $('#fileToUpload').prop('files').length == 0 ) return;
90
            $('#fileuploadform input.submit').prop('disabled',true);
91
            $("#fileuploadfailed").hide();
92
            $("#processfile").hide();
93
            $("#fileuploadstatus").show();
94
            $("form#processfile #uploadedfileid").val('');
95
            $("form#enqueuefile #uploadedfileid").val('');
96
            xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), 'temp=1', cbUpload );
97
        }
98
99
        function cbUpload( status, fileid, errors ) {
100
            if( status=='done' ) {
101
                $("form#processfile #uploadedfileid").val( fileid );
102
                $("form#enqueuefile #uploadedfileid").val( fileid );
103
                $('#fileToUpload').prop('disabled',true);
104
                $("#processfile").show();
105
                $("#enqueuefile").show();
106
            } else {
107
                var errMsgs = [ _("Error code 0 not used"), _("File already exists"), _("Directory is not writeable"), _("Root directory for uploads not defined"), _("Temporary directory for uploads not defined") ];
108
                var errCode = errors[$('#fileToUpload').prop('files')[0].name].code;
109
                $("#fileuploadstatus").hide();
110
                $("#fileuploadfailed").show();
111
                $("#fileuploadfailed").text( _("Upload status: ") +
112
                    ( status=='failed'? _("Failed") + " - (" + errCode + ") " + errMsgs[errCode]:
113
                    ( status=='denied'? _("Denied"): status ))
114
                );
115
            }
116
        }
117
118
        function CheckForm(f) {
119
            if (f.uploadedfileid.value == '') {
120
                alert(_("Please upload a file first."));
121
            } else {
122
                $("#fileuploadstatus").hide();
123
                $("#fileuploadform").slideUp();
124
                $("#mainformsubmit").prop('disabled',true);
125
                $("#queueformsubmit").prop('disabled',true);
126
                return submitBackgroundJob(f);
127
            }
128
            return false;
129
        }
130
    </script>
131
[% END %]
132
131
[% INCLUDE 'intranet-bottom.inc' %]
133
[% INCLUDE 'intranet-bottom.inc' %]
132
- 

Return to bug 19744