]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/js/ui/default/opac/ebook_api/loggedin.js
LP2061136 - Stamping 1405 DB upgrade script
[Evergreen.git] / Open-ILS / web / js / ui / default / opac / ebook_api / loggedin.js
1 /*
2  * variables defined in base_js.tt2:
3  *
4  * ou
5  * vendor_list = [ 'ebook_test' ]
6  * authtoken
7  * patron_id (barcode)
8  * myopac_page
9  * progress_icon (probably not done right)
10  *
11  * base_js.tt2 also "imports" dojo.cookie and a bunch of ebook_api JS
12  */
13
14 // Array of objects representing this patron's relationship with a specific vendor.
15 var relations = [];
16
17 // Transaction cache.
18 var xacts = {
19     checkouts: [],
20     holds_pending: [],
21     holds_ready: []
22 };
23 var ebooks = [];
24
25 // Ebook to perform actions on.
26 var active_ebook;
27 if (typeof ebook_action.title_id !== 'undefined') {
28     active_ebook = new Ebook(ebook_action.vendor, ebook_action.title_id);
29 }
30
31 dojo.addOnLoad(function() {
32
33     dojo.forEach(vendor_list, function(v) {
34         var rel = new Relation(v, patron_id);
35         relations.push(rel);
36     });
37
38     // Pull patron transaction info from cache (cookie), if available.
39     // Otherwise, do a live lookup against all enabled vendors.
40     if (dojo.cookie('ebook_xact_cache')) {
41         getCachedTransactions();
42         addTotalsToPage();
43         addTransactionsToPage();
44     } else {
45         console.log('retrieving patron transaction info for all vendors');
46         dojo.forEach(relations, function(rel) {
47             checkSession(rel.vendor, function(ses) {
48                 rel.getTransactions( function(r) {
49                     addTransactionsToCache(r);
50                 });
51             });
52         });
53     }
54
55 });
56
57 // Update current page with cross-vendor transaction totals.
58 function addTotalsToPage() {
59     console.log('updating page with transaction totals');
60     updateDashboard();
61     updateMyAccountSummary();
62 }
63
64 // Update current page with detailed transaction info, where appropriate.
65 function addTransactionsToPage() {
66     // ensure active ebook has access to session ID to avoid scoping issues during transactions
67     if (active_ebook && typeof active_ebook.vendor !== 'undefined') {
68         active_ebook.ses = active_ebook.ses || dojo.cookie(active_ebook.vendor);
69     }
70     if (dojo.byId('ebook_spinner')) dojo.addClass('ebook_spinner', "hidden");
71     if (myopac_page) {
72         console.log('updating page with cached transaction details, if applicable');
73         if (myopac_page === 'ebook_circs')
74             updateCheckoutView();
75         if (myopac_page === 'ebook_holds')
76             updateHoldView();
77         if (myopac_page === 'ebook_holds_ready')
78             updateHoldView();
79         if (myopac_page === 'ebook_checkout')
80             getReadyForCheckout();
81         if (myopac_page === 'ebook_place_hold')
82             getReadyForHold();
83     }
84 }
85         
86 function updateDashboard() {
87     console.log('updating dashboard');
88     var total_checkouts = (typeof xacts.checkouts === 'undefined') ? '-' : xacts.checkouts.length;
89     var total_holds_pending = (typeof xacts.holds_pending === 'undefined') ? '-' : xacts.holds_pending.length;
90     var total_holds_ready = (typeof xacts.holds_ready === 'undefined') ? '-' : xacts.holds_ready.length;
91     // update totals
92     var eCheckout =  document.getElementById('dash_e_checked');
93     var eHolds =  document.getElementById('dash_e_holds');
94     var ePickup =  document.getElementById('dash_e_pickup');
95     var eDash =  document.getElementById('dashboard_e');
96
97     if(typeof(eCheckout) != 'undefined' && eCheckout != null)
98     {
99         dojo.byId('dash_e_checked').innerHTML = total_checkouts;
100     }
101     if(typeof(eHolds) != 'undefined' && eHolds != null)
102     {
103         dojo.byId('dash_e_holds').innerHTML = total_holds_pending;
104     }
105     if(typeof(ePickup) != 'undefined' && ePickup != null)
106     {
107         dojo.byId('dash_e_pickup').innerHTML = total_holds_ready;
108     }
109     if(typeof(eDash) != 'undefined' && eDash != null)
110     {
111         // unhide ebook dashboard
112         dojo.removeClass('dashboard_e', "hidden");
113     }
114 }
115
116
117 function updateMyAccountSummary() {
118     if (myopac_page === 'main') {
119         console.log('updating account summary');
120         var total_checkouts = (typeof xacts.checkouts === 'undefined') ? '-' : xacts.checkouts.length;
121         var total_holds_pending = (typeof xacts.holds_pending === 'undefined') ? '-' : xacts.holds_pending.length;
122         var total_holds_ready = (typeof xacts.holds_ready === 'undefined') ? '-' : xacts.holds_ready.length;
123         // update totals
124         dojo.byId('acct_sum_ebook_circ_total').innerHTML = total_checkouts;
125         dojo.byId('acct_sum_ebook_hold_total').innerHTML = total_holds_pending;
126         dojo.byId('acct_sum_ebook_hold_ready_total').innerHTML = total_holds_ready;
127         // unhide display elements
128         dojo.removeClass('acct_sum_ebook_circs', "hidden");
129         dojo.removeClass('acct_sum_ebook_holds', "hidden");
130         dojo.removeClass('acct_sum_ebook_holds_ready', "hidden");
131     }
132 }
133
134 function updateCheckoutView() {
135     if (xacts.checkouts.length < 1) {
136         dojo.removeClass('no_ebook_circs', "hidden");
137     } else {
138         dojo.empty('ebook_circs_main_table_body');
139         dojo.forEach(xacts.checkouts, function(x) {
140             var ebook = new Ebook(x.vendor, x.title_id);
141             var tr = dojo.create("tr", null, dojo.byId('ebook_circs_main_table_body'));
142             dojo.create("td", { innerHTML: x.title }, tr);
143             dojo.create("td", { innerHTML: x.author }, tr);
144             dojo.create("td", { innerHTML: x.due_date }, tr);
145             var dl_td = dojo.create("td", null, tr);
146             if (x.download_url) {
147                 dl_td.innerHTML = '<a href="' + x.download_url + '">' + l_strings.download + '</a>';
148             }
149             if (x.download_redirect) {
150                 dl_td.innerHTML = '<a target="_blank" href="' + x.download_redirect + '">' + l_strings.download + '</a>';
151             } else if (x.formats) {
152                 var select = dojo.create("select", { id: "download-format" }, dl_td);
153                 for (f in x.formats) {
154                     dojo.create("option", { value: x.formats[f], innerHTML: f }, select);
155                 }
156                 var button = dojo.create("input", { id: "download-button", type: "button", value: l_strings.download }, dl_td);
157                 ebook.conns.download = dojo.connect(button, 'onclick', ebook, "download");
158             }
159             // TODO: more actions (renew, checkin)
160             ebooks.push(ebook);
161         });
162         dojo.addClass('no_ebook_circs', "hidden");
163         dojo.removeClass('ebook_circs_main', "hidden");
164     }
165 }
166
167 function updateHoldView() {
168     if (myopac_page === 'ebook_holds_ready') {
169         // only show holds that are ready for checkout
170         var holds = xacts.holds_ready;
171     } else {
172         var holds_pending = xacts.holds_pending;
173         var holds_ready = xacts.holds_ready;
174
175         // combine all holds into a single list, ready-for-checkout holds first
176         var holds = holds_ready.concat(holds_pending);
177     }
178
179     if (holds.length < 1) {
180         dojo.removeClass('no_ebook_holds', "hidden");
181     } else {
182         dojo.empty('ebook_holds_main_table_body');
183         dojo.forEach(holds, function(h) {
184             var hold_status;
185             if (h.is_ready) {
186                 hold_status = l_strings.ready_for_checkout;
187             } else if (h.is_frozen) {
188                 hold_status = l_strings.suspended;
189             } else {
190                 hold_status = h.queue_position + ' / ' + h.queue_size;
191             }
192             h.doCancelHold = function() {
193                 var vendor = this.vendor;
194                 var title_id = this.title_id;
195                 checkSession(vendor, function() {
196                     var ebook = new Ebook(vendor, title_id);
197                     ebook.cancelHold(authtoken, patron_id, function(resp) {
198                         if (resp.error_msg) {
199                             console.log('Cancel hold failed: ' + resp.error_msg);
200                             dojo.removeClass('ebook_cancel_hold_failed', "hidden");
201                         } else {
202                             console.log('Cancel hold succeeded!');
203                             dojo.destroy("hold-" + ebook.id);
204                             dojo.removeClass('ebook_cancel_hold_succeeded', "hidden");
205                             // Updating the transaction cache to remove the canceled hold
206                             // is inconvenient, so we skip cleanupAfterAction() and merely
207                             // clear transaction cache to force a refresh on next page load.
208                             dojo.cookie('ebook_xact_cache', '', {path: '/', expires: '-1h'});
209                         }
210                     });
211                 });
212             };
213             var tr = dojo.create("tr", { id: "hold-" + h.title_id }, dojo.byId('ebook_holds_main_table_body'));
214             dojo.create("td", { innerHTML: h.title }, tr);
215             dojo.create("td", { innerHTML: h.author }, tr);
216             dojo.create("td", { innerHTML: h.expire_date }, tr);
217             dojo.create("td", { innerHTML: hold_status }, tr);
218             var actions_td = dojo.create("td", null, tr);
219             var button = dojo.create("input", { id: "cancel-hold-" + h.title_id, type: "button", value: l_strings.cancel_hold }, actions_td);
220             dojo.connect(button, 'onclick', h, "doCancelHold");
221         });
222         dojo.addClass('no_ebook_holds', "hidden");
223         dojo.removeClass('ebook_holds_main', "hidden");
224     }
225 }
226
227 // set up page for user to perform a checkout
228 function getReadyForCheckout() {
229     if (typeof ebook_action.type === 'undefined')
230         return;
231     if (typeof active_ebook === 'undefined') {
232         console.log('No active ebook specified, cannot prepare for checkout');
233         dojo.removeClass('ebook_checkout_failed', "hidden");
234     } else {
235         active_ebook.getDetails( function(ebook) {
236             dojo.empty('ebook_circs_main_table_body');
237             var tr = dojo.create("tr", null, dojo.byId('ebook_circs_main_table_body'));
238             dojo.create("td", { innerHTML: ebook.title }, tr);
239             dojo.create("td", { innerHTML: ebook.author }, tr);
240             dojo.create("td", null, tr);
241             dojo.create("td", { id: "checkout-button-td" }, tr);
242             if (typeof active_ebook.formats !== 'undefined') {
243                 var select = dojo.create("select", { id: "checkout-format" }, dojo.byId('checkout-button-td'));
244                 dojo.forEach(active_ebook.formats, function(f) {
245                     dojo.create("option", { value: f.id, innerHTML: f.name }, select);
246                 });
247             }
248             var button = dojo.create("input", { id: "checkout-button", type: "button", value: l_strings.checkout }, dojo.byId('checkout-button-td'));
249             ebook.conns.checkout = dojo.connect(button, 'onclick', "doCheckout");
250             dojo.removeClass('ebook_circs_main', "hidden");
251         });
252     }
253 }
254
255 // set up page for user to place a hold
256 function getReadyForHold() {
257     if (typeof ebook_action.type === 'undefined')
258         return;
259     if (typeof active_ebook === 'undefined') {
260         console.log('No active ebook specified, cannot prepare for hold');
261         dojo.removeClass('ebook_hold_failed', "hidden");
262     } else {
263         active_ebook.getDetails( function(ebook) {
264             dojo.empty('ebook_holds_main_table_body');
265             var tr = dojo.create("tr", null, dojo.byId('ebook_holds_main_table_body'));
266             dojo.create("td", { innerHTML: ebook.title }, tr);
267             dojo.create("td", { innerHTML: ebook.author }, tr);
268             dojo.create("td", null, tr); // Expire Date
269             dojo.create("td", null, tr); // Status
270             dojo.create("td", { id: "hold-button-td" }, tr);
271             if (ebook_action.type == 'place_hold') {
272                 var button = dojo.create("input", { id: "hold-button", type: "button", value: l_strings.place_hold }, dojo.byId('hold-button-td'));
273                 ebook.conns.checkout = dojo.connect(button, 'onclick', "doPlaceHold");
274             }
275             dojo.removeClass('ebook_holds_main', "hidden");
276         });
277     }
278 }
279
280 function cleanupAfterAction() {
281     // unset variables related to the transaction we have performed,
282     // to avoid any weirdness on page reload
283     ebook_action = {};
284     // update page to account for successful checkout
285     addTotalsToPage();
286     addTransactionsToPage();
287     // clear transaction cache to force a refresh on next page load
288     dojo.cookie('ebook_xact_cache', '', {path: '/', expires: '-1h'});
289 }
290
291 // check out our active ebook
292 function doCheckout() {
293     var ses = dojo.cookie(active_ebook.vendor); // required when inspecting checkouts for download_url
294     active_ebook.checkout(authtoken, patron_id, function(resp) {
295         if (resp.error_msg) {
296             console.log('Checkout failed: ' + resp.error_msg);
297             dojo.removeClass('ebook_checkout_failed', "hidden");
298             return;
299         }
300         console.log('Checkout succeeded!');
301         dojo.destroy('checkout-button');
302         dojo.destroy('checkout-format'); // remove optional format selector
303         dojo.removeClass('ebook_checkout_succeeded', "hidden");
304         // add our successful checkout to top of transaction cache
305         var new_xact = {
306             title_id: active_ebook.id,
307             title: active_ebook.title,
308             author: active_ebook.author,
309             due_date: resp.due_date,
310             finish: function() {
311                 console.log('new_xact.finish()');
312                 xacts.checkouts.unshift(this);
313                 cleanupAfterAction();
314                 // When we switch to jQuery, we can use .one() instead of .on(),
315                 // obviating the need for an explicit disconnect here.
316                 dojo.disconnect(active_ebook.conns.checkout);
317             }
318         };
319         if (resp.download_url) {
320             // Use download URL from checkout response, if available.
321             new_xact.download_url = resp.download_url;
322             dojo.create("a", { href: new_xact.download_url, innerHTML: l_strings.download }, dojo.byId('checkout-button-td'));
323             new_xact.finish();
324         } else if (resp.download_redirect) {
325             // Use download URL from checkout response, if available.
326             new_xact.download_redirect = resp.download_redirect;
327             dojo.create("a", { target: "_blank", href: new_xact.download_redirect, innerHTML: l_strings.download }, dojo.byId('checkout-button-td'));
328             new_xact.finish();
329         } else if (typeof resp.formats !== 'undefined') {
330             // User must select download format from list of options.
331             var select = dojo.create("select", { id: "download-format" }, dojo.byId('checkout-button-td'));
332             for (f in resp.formats) {
333                 dojo.create("option", { value: resp.formats[f], innerHTML: f }, select);
334             }
335             var button = dojo.create("input", { id: "download-button", type: "button", value: l_strings.download }, dojo.byId('checkout-button-td'));
336             active_ebook.conns.download = dojo.connect(button, 'onclick', active_ebook, "download");
337             new_xact.finish();
338         } else if (typeof resp.xact_id !== 'undefined') {
339             // No download URL provided by API checkout response.  Grab fresh
340             // list of user checkouts from API, find the just-completed
341             // checkout by transaction ID, and get the download URL from that.
342             // We call the OpenSRF method directly because Relation.getCheckouts()
343             // results in scoping issues when retrieving the vendor session cookie.
344             new_xact.xact_id = resp.xact_id;
345             new OpenSRF.ClientSession('open-ils.ebook_api').request({
346                 method: 'open-ils.ebook_api.patron.get_checkouts',
347                 params: [ authtoken, ses, patron_id ],
348                 async: false,
349                 oncomplete: function(r) {
350                     var resp = r.recv();
351                     if (resp) {
352                         dojo.forEach(resp.content(), function(x) {
353                             if (x.xact_id === new_xact.xact_id) {
354                                 new_xact.download_url = x.download_url;
355                                 dojo.create("a", { href: new_xact.download_url, innerHTML: l_strings.download }, dojo.byId('checkout-button-td'));
356                                 return;
357                             }
358                         });
359                         new_xact.finish();
360                     }
361                 }
362             }).send();
363         }
364     });
365 }
366
367 // place hold on our active ebook
368 function doPlaceHold() {
369     active_ebook.placeHold(authtoken, patron_id, function(resp) {
370         if (resp.error_msg) {
371             console.log('Place hold failed: ' + resp.error_msg);
372             dojo.removeClass('ebook_place_hold_failed', "hidden");
373         } else {
374             console.log('Place hold succeeded!');
375             dojo.destroy('hold-button');
376             dojo.removeClass('ebook_place_hold_succeeded', "hidden");
377             var new_hold = {
378                 title_id: active_ebook.id,
379                 title: active_ebook.title,
380                 author: active_ebook.author,
381                 queue_position: resp.queue_position,
382                 queue_size: resp.queue_size,
383                 expire_date: resp.expire_date
384             };
385             if ( resp.is_ready || (resp.queue_position === 1 && resp.queue_size === 1) ) {
386                 xacts.holds_ready.unshift(new_hold);
387             } else {
388                 xacts.holds_pending.unshift(new_hold);
389             }
390             cleanupAfterAction();
391         }
392     });
393 }
394
395 // deserialize transactions from cache, returning them as a JS object
396 function getCachedTransactions() {
397     console.log('retrieving cached transaction details');
398     var cache_obj;
399     var current_cache = dojo.cookie('ebook_xact_cache');
400     if (current_cache) {
401         cache_obj = JSON.parse(current_cache);
402         xacts.checkouts = cache_obj.checkouts;
403         xacts.holds_pending = cache_obj.holds_pending;
404         xacts.holds_ready = cache_obj.holds_ready;
405     }
406     return cache_obj;
407 }
408
409 // add a single vendor's transactions to transaction cache
410 function addTransactionsToCache(rel) {
411     console.log('updating transaction cache');
412     var v = rel.vendor;
413     var updated_xacts = {
414         checkouts: [],
415         holds_pending: [],
416         holds_ready: []
417     };
418     // preserve any transactions with other vendors
419     dojo.forEach(xacts.checkouts, function(xact) {
420         if (xact.vendor !== v)
421             updated_xacts.checkouts.push(xact);
422     });
423     dojo.forEach(xacts.holds_pending, function(xact) {
424         if (xact.vendor !== v)
425             updated_xacts.holds_pending.push(xact);
426     });
427     dojo.forEach(xacts.holds_ready, function(xact) {
428         if (xact.vendor !== v)
429             updated_xacts.holds_ready.push(xact);
430     });
431     // add transactions from current vendor
432     dojo.forEach(rel.checkouts, function(xact) {
433         updated_xacts.checkouts.push(xact);
434     });
435     dojo.forEach(rel.holds_pending, function(xact) {
436         updated_xacts.holds_pending.push(xact);
437     });
438     dojo.forEach(rel.holds_ready, function(xact) {
439         updated_xacts.holds_ready.push(xact);
440     });
441     // TODO sort transactions by date
442     // save transactions to cache
443     xacts = updated_xacts;
444     var new_cache = JSON.stringify(xacts);
445     dojo.cookie('ebook_xact_cache', new_cache, {path: '/'});
446     // update current page
447     addTotalsToPage();
448     addTransactionsToPage();
449 }
450