@internetarchive/ia-book-actions 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/assets/data/lending-get-status-service.js +2 -2
- package/src/components/collapsible-action-group.js +10 -4
- package/src/components/timer-countdown.js +2 -1
- package/src/core/services/get-lending-actions.js +3 -4
- package/src/core/services/loan-analytics.js +8 -8
- package/src/core/services/loan-renew-helper.js +2 -2
- package/src/ia-book-actions.js +216 -92
- package/test/core/services/loan-renew-helper.test.js +1 -1
- package/test/ia-book-actions.test.js +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
"test:watch": "web-test-runner --watch --playwright --browsers chromium firefox webkit"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"@internetarchive/ia-activity-indicator": "^0.0.4",
|
|
21
22
|
"@internetarchive/icon-info": "^1.2.6",
|
|
22
23
|
"@internetarchive/local-cache": "^0.2.1",
|
|
23
|
-
"@internetarchive/modal-manager": "^0.2.
|
|
24
|
+
"@internetarchive/modal-manager": "^0.2.12",
|
|
24
25
|
"@internetarchive/shared-resize-observer": "^0.2.0",
|
|
25
26
|
"@internetarchive/toast-manager": "0.1.0",
|
|
26
27
|
"lit": "^2.5.0"
|
|
@@ -100,7 +100,7 @@ export const canBrowseAndBorrow = {
|
|
|
100
100
|
// userid: "",
|
|
101
101
|
bookUrl: '/details/practicalorganic00plim',
|
|
102
102
|
daysLeftOnLoan: 0,
|
|
103
|
-
isAdmin:
|
|
103
|
+
isAdmin: false,
|
|
104
104
|
isArchiveOrgLending: true,
|
|
105
105
|
isAvailable: false,
|
|
106
106
|
isAvailableForBrowsing: false,
|
|
@@ -118,7 +118,7 @@ export const canBrowseAndBorrow = {
|
|
|
118
118
|
loanStartDate: '2021-07-30 09:57:40',
|
|
119
119
|
loansUrl: '/details/@neeraj-archive?tab=loans#loans-on-loan',
|
|
120
120
|
maxLoans: 10,
|
|
121
|
-
secondsLeftOnLoan:
|
|
121
|
+
secondsLeftOnLoan: 155,
|
|
122
122
|
shouldProtectImages: true,
|
|
123
123
|
totalWaitlistCount: 0,
|
|
124
124
|
userHasBorrowed: false,
|
|
@@ -30,6 +30,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
30
30
|
returnUrl: { type: String },
|
|
31
31
|
autoRenew: { type: Boolean },
|
|
32
32
|
autoReturn: { type: Boolean },
|
|
33
|
+
returnNow: { type: Boolean },
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -51,6 +52,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
51
52
|
this.returnUrl = '';
|
|
52
53
|
this.autoRenew = false;
|
|
53
54
|
this.autoReturn = false;
|
|
55
|
+
this.returnNow = false;
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
updated(changed) {
|
|
@@ -68,18 +70,22 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
68
70
|
if (changed.has('autoReturn') && this.autoReturn === true) {
|
|
69
71
|
this.dispatchLoanEvent('autoReturn');
|
|
70
72
|
}
|
|
73
|
+
|
|
74
|
+
if (changed.has('returnNow') && this.returnNow === true) {
|
|
75
|
+
this.dispatchLoanEvent('returnNow', { borrowType: 'browse' });
|
|
76
|
+
}
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
/**
|
|
74
|
-
* dispatch event when book is auto renewed / returned
|
|
80
|
+
* dispatch event when book is auto auto-renewed / auto-returned / returned
|
|
75
81
|
* listen these events in action-handler.js to execute ajax call on petabox.
|
|
76
82
|
* @see ActionsHandler
|
|
77
83
|
*
|
|
78
|
-
* @param {string} event - autoRenew|autoReturn
|
|
84
|
+
* @param {string} event - autoRenew|autoReturn|returnNow
|
|
79
85
|
* @memberof CollapsibleActionGroup
|
|
80
86
|
*/
|
|
81
|
-
dispatchLoanEvent(event) {
|
|
82
|
-
this.dispatchEvent(new
|
|
87
|
+
dispatchLoanEvent(event, detail) {
|
|
88
|
+
this.dispatchEvent(new CustomEvent(event, { detail }));
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
/**
|
|
@@ -41,7 +41,7 @@ export default class TimerCountdown extends LitElement {
|
|
|
41
41
|
* delay seconds in setInterval function
|
|
42
42
|
* @type {number}
|
|
43
43
|
*/
|
|
44
|
-
this.timerExecutionSeconds =
|
|
44
|
+
this.timerExecutionSeconds = 30;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
disconnectedCallback() {
|
|
@@ -66,6 +66,7 @@ export default class TimerCountdown extends LitElement {
|
|
|
66
66
|
// store current time
|
|
67
67
|
this.timeWhenTimerStart = new Date();
|
|
68
68
|
|
|
69
|
+
// this.dispatchLoanRenewEvent(secondsLeft);
|
|
69
70
|
/**
|
|
70
71
|
* set interval in window object
|
|
71
72
|
* @see ia-lending-intervals.js
|
|
@@ -40,7 +40,7 @@ import ActionsConfig from './actions-config.js';
|
|
|
40
40
|
* @enum {string}
|
|
41
41
|
*/
|
|
42
42
|
export const bookTitles = {
|
|
43
|
-
available_1hr: 'Renews
|
|
43
|
+
available_1hr: 'Renews automatically as long as pages are turned.',
|
|
44
44
|
available_14d: 'This book can be borrowed for 14 days.',
|
|
45
45
|
available_pd: 'Book available to patrons with print disabilities.',
|
|
46
46
|
available_waitlist: 'A waitlist is available.',
|
|
@@ -49,7 +49,7 @@ export const bookTitles = {
|
|
|
49
49
|
being_borrowed: 'Another patron is using this book. Please check back later.',
|
|
50
50
|
eligible_pd: 'You are eligible for print-disabled access.',
|
|
51
51
|
on_waitlist: 'You are on the waitlist for this book.',
|
|
52
|
-
session_expired: '',
|
|
52
|
+
session_expired: 'Renews automatically as long as pages are turned.',
|
|
53
53
|
unavailable: 'This book is not available at this time.',
|
|
54
54
|
};
|
|
55
55
|
|
|
@@ -98,8 +98,7 @@ export class GetLendingActions {
|
|
|
98
98
|
let isBrowsing =
|
|
99
99
|
lendingStatus.user_has_browsed && !lendingStatus.browsingExpired;
|
|
100
100
|
if (isBrowsing) {
|
|
101
|
-
primaryTitleText =
|
|
102
|
-
'Returns automatically after 25 minutes of inactivity.';
|
|
101
|
+
primaryTitleText = bookTitles.available_1hr;
|
|
103
102
|
} else {
|
|
104
103
|
primaryTitleText = `Your loan of this book has ${lendingStatus.daysLeftOnLoan} days left.`;
|
|
105
104
|
}
|
|
@@ -144,14 +144,14 @@ export default class LoanAnanlytics {
|
|
|
144
144
|
* @memberof LoanAnanlytics
|
|
145
145
|
*/
|
|
146
146
|
sendEvent(eventCategory, eventAction, label, extraParams) {
|
|
147
|
-
console.log(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
);
|
|
147
|
+
// console.log(
|
|
148
|
+
// 'eventCategory:-',
|
|
149
|
+
// eventCategory,
|
|
150
|
+
// '\t||\teventAction:-',
|
|
151
|
+
// eventAction,
|
|
152
|
+
// '\t||\tlabel:-',
|
|
153
|
+
// label
|
|
154
|
+
// );
|
|
155
155
|
|
|
156
156
|
window?.archive_analytics?.send_event_no_sampling(
|
|
157
157
|
eventCategory,
|
|
@@ -16,7 +16,7 @@ export class LoanRenewHelper {
|
|
|
16
16
|
this.loanRenewMessage =
|
|
17
17
|
'This book has been renewed for #time #unitsOfTime.';
|
|
18
18
|
this.loanReturnWarning =
|
|
19
|
-
'
|
|
19
|
+
'With no action, this book will be auto-returned in #time #unitsOfTime.';
|
|
20
20
|
|
|
21
21
|
// private props
|
|
22
22
|
this.result = {
|
|
@@ -39,7 +39,7 @@ export class LoanRenewHelper {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Trigger this function when user has browsed a book and change the
|
|
42
|
+
* Trigger this function when user has browsed a book and change the page
|
|
43
43
|
* - every time user change the page, we set current time in indexedDB
|
|
44
44
|
* - also check if need to auto renew current loan
|
|
45
45
|
*
|
package/src/ia-book-actions.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable camelcase */
|
|
2
|
+
/* eslint-disable class-methods-use-this */
|
|
2
3
|
import { html, css, LitElement, nothing } from 'lit';
|
|
3
4
|
|
|
4
5
|
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
|
@@ -23,6 +24,21 @@ export const events = {
|
|
|
23
24
|
browseExpired: 'IABookReader:BrowsingHasExpired',
|
|
24
25
|
};
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* custom styling for modal-manager buttons
|
|
29
|
+
* TODO: lets allow modal-manager to know ia-button classes
|
|
30
|
+
*/
|
|
31
|
+
export const modalButtonStyle = {
|
|
32
|
+
iaButton:
|
|
33
|
+
'min-height:3.5rem;cursor:pointer;color:white;border-radius:0.4rem;border:1px solid #c5d1df;padding:4px 8px;width:auto;user-select:none;',
|
|
34
|
+
renew: 'background:#194880;width:110px;',
|
|
35
|
+
return: 'background:#d9534f;width:120px;',
|
|
36
|
+
loaderIcon:
|
|
37
|
+
'display:inline-block;width:20px;height:20px;margin-top:2px;color:white;--activityIndicatorLoadingRingColor:#fff;--activityIndicatorLoadingDotColor:#fff;',
|
|
38
|
+
refresh:
|
|
39
|
+
'background:none;font-size:inherit;border:0;padding:0;color:#0000ee;cursor:pointer;text-decoration:underline',
|
|
40
|
+
};
|
|
41
|
+
|
|
26
42
|
export default class IABookActions extends LitElement {
|
|
27
43
|
static get properties() {
|
|
28
44
|
return {
|
|
@@ -71,10 +87,19 @@ export default class IABookActions extends LitElement {
|
|
|
71
87
|
this.secondaryActions = [];
|
|
72
88
|
this.lendingOptions = {};
|
|
73
89
|
this.borrowType = ''; // (browsed|borrowed)
|
|
74
|
-
this.
|
|
90
|
+
this.browseTimer = undefined;
|
|
91
|
+
|
|
92
|
+
/** @deprecated */
|
|
93
|
+
this.toast = undefined;
|
|
94
|
+
/** @deprecated */
|
|
75
95
|
this.suppressToast = false;
|
|
96
|
+
/** @deprecated */
|
|
76
97
|
this.suppressAutoRenew = false;
|
|
77
|
-
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* when user click on [return the book] button on warning modal
|
|
101
|
+
*/
|
|
102
|
+
this.returnNow = false;
|
|
78
103
|
|
|
79
104
|
/**
|
|
80
105
|
* contains one hour auto-loan-renew time configuration
|
|
@@ -218,8 +243,9 @@ export default class IABookActions extends LitElement {
|
|
|
218
243
|
}
|
|
219
244
|
|
|
220
245
|
if (this.borrowType === 'browsed') {
|
|
246
|
+
console.log('this.borrowType', this.borrowType);
|
|
221
247
|
// start timer for browsed.
|
|
222
|
-
this.startBrowseTimer();
|
|
248
|
+
await this.startBrowseTimer();
|
|
223
249
|
}
|
|
224
250
|
|
|
225
251
|
// early return if not borrowed or no action-bar
|
|
@@ -248,57 +274,25 @@ export default class IABookActions extends LitElement {
|
|
|
248
274
|
* Bind 1 hour loan auto renew event,
|
|
249
275
|
* There are two events we want to use,
|
|
250
276
|
* 1. BookReader:userAction - dispatched from bookreader side
|
|
251
|
-
* 2.
|
|
252
|
-
* 3. IABookActions:loanRenew - dispatched from timer-countdown component
|
|
277
|
+
* 2. IABookActions:loanRenew - dispatched from timer-countdown component
|
|
253
278
|
*/
|
|
254
279
|
bindLoanRenewEvents() {
|
|
255
280
|
/**
|
|
256
281
|
* dispatched this event from bookreader page changed
|
|
257
282
|
*/
|
|
258
283
|
window.addEventListener('BookReader:userAction', () => {
|
|
259
|
-
console.log('** BR user Action', {
|
|
260
|
-
suppressAutoRenew: this.suppressAutoRenew,
|
|
261
|
-
borrowType: this.borrowType,
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
this.suppressToast = true;
|
|
265
|
-
this.closeToastManager();
|
|
266
|
-
|
|
267
|
-
if (this.suppressAutoRenew) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
284
|
if (this.borrowType === 'browsed') {
|
|
272
285
|
this.autoLoanRenewChecker(true);
|
|
273
286
|
}
|
|
274
287
|
});
|
|
275
288
|
|
|
276
|
-
/**
|
|
277
|
-
* detect click-event on document to close toast-template
|
|
278
|
-
*/
|
|
279
|
-
document.addEventListener('click', e => {
|
|
280
|
-
console.log('*** top level click handler to remove toast on click');
|
|
281
|
-
if (this.loanRenewHelper && this.loanRenewResult.secondsLeft > 0) {
|
|
282
|
-
this.suppressToast = true;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// reload when user click on book-page and book is EXPIRED
|
|
286
|
-
const hasExpired =
|
|
287
|
-
'browsingExpired' in this.lendingStatus &&
|
|
288
|
-
this.lendingStatus?.browsingExpired;
|
|
289
|
-
if (hasExpired && e.target.nodeName !== 'IA-BOOK-ACTIONS') {
|
|
290
|
-
window.location?.reload();
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
|
|
294
289
|
/**
|
|
295
290
|
* this event dispatched from timer-countdown component for:
|
|
296
|
-
* 1. user turned book page after showing auto-returned warning
|
|
297
|
-
* 2. show warning
|
|
291
|
+
* 1. user turned book page after showing auto-returned warning modal
|
|
292
|
+
* 2. show warning modal having remaining time
|
|
298
293
|
* @see TimerCountdown::timerCountdown
|
|
299
294
|
*/
|
|
300
295
|
this.addEventListener('IABookActions:loanRenew', async event => {
|
|
301
|
-
console.log('** IABookActions:loanRenew', event.detail);
|
|
302
296
|
await this.autoLoanRenewChecker(false);
|
|
303
297
|
|
|
304
298
|
/**
|
|
@@ -314,16 +308,16 @@ export default class IABookActions extends LitElement {
|
|
|
314
308
|
this.browseHasExpired();
|
|
315
309
|
}
|
|
316
310
|
|
|
317
|
-
// show warning
|
|
311
|
+
// show warning modal with remaining time to auto returned it.
|
|
318
312
|
if (this.loanRenewResult.renewNow === false) {
|
|
319
313
|
/**
|
|
320
314
|
* so compensate for the 50 second buffer to handle above race conditions
|
|
321
315
|
* let's reduce 1 min from warning texts and early return the book when 1 min left.
|
|
322
316
|
*/
|
|
323
317
|
secondsLeft -= 60;
|
|
324
|
-
|
|
325
318
|
this.loanRenewResult.secondsLeft = secondsLeft;
|
|
326
|
-
|
|
319
|
+
|
|
320
|
+
this.showWarningModal();
|
|
327
321
|
}
|
|
328
322
|
});
|
|
329
323
|
}
|
|
@@ -347,17 +341,153 @@ export default class IABookActions extends LitElement {
|
|
|
347
341
|
}
|
|
348
342
|
|
|
349
343
|
/**
|
|
344
|
+
* create / select the modal-manager component on DOM
|
|
345
|
+
* @memberof IABookActions
|
|
346
|
+
*/
|
|
347
|
+
async useModalManager() {
|
|
348
|
+
if (!this.modal) {
|
|
349
|
+
this.modal = document.querySelector('modal-manager');
|
|
350
|
+
|
|
351
|
+
if (!this.modal) this.modal = document.createElement('modal-manager');
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
this.modal.id = 'action-bar-modal';
|
|
355
|
+
await document.body.appendChild(this.modal);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Show the waring modal to ask user if they are still reading
|
|
360
|
+
*/
|
|
361
|
+
async showWarningModal() {
|
|
362
|
+
console.log('****** showWarningModal ******');
|
|
363
|
+
await this.useModalManager();
|
|
364
|
+
|
|
365
|
+
// if secondsLeft < 60, consider it 1 minute
|
|
366
|
+
let { secondsLeft } = this.loanRenewResult;
|
|
367
|
+
if (secondsLeft === undefined) {
|
|
368
|
+
secondsLeft = this.lendingStatus.secondsLeftOnLoan;
|
|
369
|
+
} else {
|
|
370
|
+
secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const config = new ModalConfig();
|
|
374
|
+
config.headline = 'Are you still here?';
|
|
375
|
+
config.showCloseButton = false;
|
|
376
|
+
config.closeOnBackdropClick = false;
|
|
377
|
+
config.message = this.loanRenewHelper?.getMessageTexts(
|
|
378
|
+
this.loanRenewResult.texts,
|
|
379
|
+
secondsLeft
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const customContent = html`<br />
|
|
383
|
+
<div id="custom-buttons" style="display:flex;justify-content:center;">
|
|
384
|
+
<button
|
|
385
|
+
style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
|
|
386
|
+
@click=${event => {
|
|
387
|
+
this.changeModalState(event);
|
|
388
|
+
this.autoLoanRenewChecker(true);
|
|
389
|
+
}}
|
|
390
|
+
>
|
|
391
|
+
Keep reading
|
|
392
|
+
</button>
|
|
393
|
+
<button
|
|
394
|
+
style="${modalButtonStyle.iaButton} ${modalButtonStyle.return}"
|
|
395
|
+
@click=${event => {
|
|
396
|
+
this.changeModalState(event);
|
|
397
|
+
document.querySelector('ia-book-actions').disableActionGroup = true;
|
|
398
|
+
this.returnNow = true;
|
|
399
|
+
}}
|
|
400
|
+
>
|
|
401
|
+
Return the book
|
|
402
|
+
</button>
|
|
403
|
+
</div> `;
|
|
404
|
+
|
|
405
|
+
this.modal.showModal({ config, customModalContent: customContent });
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* helper function to change button click states on modal-manager
|
|
410
|
+
* - add loader on button click
|
|
411
|
+
* - change button appearance
|
|
412
|
+
*
|
|
413
|
+
* @param {Event} event
|
|
414
|
+
*/
|
|
415
|
+
changeModalState(event) {
|
|
416
|
+
if (event.target === undefined) return;
|
|
417
|
+
|
|
418
|
+
const button = event.target;
|
|
419
|
+
button.innerHTML = `<ia-activity-indicator
|
|
420
|
+
mode="processing"
|
|
421
|
+
style=${modalButtonStyle.loaderIcon}
|
|
422
|
+
></ia-activity-indicator>`;
|
|
423
|
+
|
|
424
|
+
const parentElement = event.target.parentNode;
|
|
425
|
+
parentElement.style.pointerEvents = 'none';
|
|
426
|
+
parentElement.style.opacity = 0.8;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Show modal when book is auto returned
|
|
431
|
+
*/
|
|
432
|
+
async showExpiredModal() {
|
|
433
|
+
await this.useModalManager();
|
|
434
|
+
|
|
435
|
+
const config = new ModalConfig();
|
|
436
|
+
config.headline = '';
|
|
437
|
+
config.showCloseButton = false;
|
|
438
|
+
config.closeOnBackdropClick = false;
|
|
439
|
+
config.message = 'This book has been returned due to inactivity.';
|
|
440
|
+
|
|
441
|
+
const customContent = html`<br />
|
|
442
|
+
<div style="text-align: center">
|
|
443
|
+
<button
|
|
444
|
+
style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
|
|
445
|
+
@click=${() => {
|
|
446
|
+
window.location?.reload();
|
|
447
|
+
}}
|
|
448
|
+
>
|
|
449
|
+
Okay
|
|
450
|
+
</button>
|
|
451
|
+
</div> `;
|
|
452
|
+
|
|
453
|
+
this.modal?.showModal({ config, customModalContent: customContent });
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* close/hide modal-manager
|
|
458
|
+
*/
|
|
459
|
+
async closeModalManager() {
|
|
460
|
+
this.modal = document.querySelector('modal-manager');
|
|
461
|
+
this.modal?.closeModal();
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* @deprecated
|
|
466
|
+
* create / select the toast-template component on DOM
|
|
467
|
+
*
|
|
468
|
+
* @memberof IABookActions
|
|
469
|
+
*/
|
|
470
|
+
async useToastManager() {
|
|
471
|
+
if (!this.toast) {
|
|
472
|
+
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
473
|
+
|
|
474
|
+
if (!this.toast) this.toast = document.createElement('toast-template');
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
await this.shadowRoot.appendChild(this.toast);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* @deprecated
|
|
350
482
|
* close/hide toast message
|
|
351
483
|
*/
|
|
352
484
|
async closeToastManager() {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if (toastTemplate) {
|
|
356
|
-
toastTemplate?.remove();
|
|
357
|
-
}
|
|
485
|
+
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
486
|
+
this.toast?.remove();
|
|
358
487
|
}
|
|
359
488
|
|
|
360
489
|
/**
|
|
490
|
+
* @deprecated
|
|
361
491
|
* Show toast messages on some specific loan renew features. e.g.
|
|
362
492
|
* - show message when book is auto renewed
|
|
363
493
|
* - show message when book is expired
|
|
@@ -370,11 +500,7 @@ export default class IABookActions extends LitElement {
|
|
|
370
500
|
});
|
|
371
501
|
if (this.suppressToast) return;
|
|
372
502
|
|
|
373
|
-
|
|
374
|
-
if (!toastTemplate) {
|
|
375
|
-
toastTemplate = document.createElement('toast-template');
|
|
376
|
-
}
|
|
377
|
-
await this.shadowRoot.appendChild(toastTemplate);
|
|
503
|
+
await this.useToastManager();
|
|
378
504
|
|
|
379
505
|
// if secondsLeft < 60, consider it 1 minute
|
|
380
506
|
let { secondsLeft } = this.loanRenewResult;
|
|
@@ -391,12 +517,15 @@ export default class IABookActions extends LitElement {
|
|
|
391
517
|
secondsLeft
|
|
392
518
|
);
|
|
393
519
|
|
|
394
|
-
|
|
520
|
+
this.toast?.showToast({
|
|
395
521
|
config,
|
|
396
522
|
});
|
|
397
523
|
}
|
|
398
524
|
|
|
399
525
|
async browseHasRenew() {
|
|
526
|
+
console.log('****** browseHasRenew ******');
|
|
527
|
+
window?.IALendingIntervals?.clearAll();
|
|
528
|
+
|
|
400
529
|
const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
|
|
401
530
|
const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
|
|
402
531
|
|
|
@@ -407,24 +536,6 @@ export default class IABookActions extends LitElement {
|
|
|
407
536
|
secondsLeftOnLoan: secondsLeft,
|
|
408
537
|
};
|
|
409
538
|
this.lendingStatus = currStatus;
|
|
410
|
-
|
|
411
|
-
this.startBrowseTimer();
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
startBrowseTimer() {
|
|
415
|
-
clearTimeout(this.browseTimer);
|
|
416
|
-
const {
|
|
417
|
-
browsingExpired,
|
|
418
|
-
user_has_browsed,
|
|
419
|
-
secondsLeftOnLoan,
|
|
420
|
-
} = this.lendingStatus;
|
|
421
|
-
if (!user_has_browsed || browsingExpired) {
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
this.browseTimer = setTimeout(() => {
|
|
426
|
-
this.browseHasExpired();
|
|
427
|
-
}, secondsLeftOnLoan * 1000);
|
|
428
539
|
}
|
|
429
540
|
|
|
430
541
|
/**
|
|
@@ -443,14 +554,33 @@ export default class IABookActions extends LitElement {
|
|
|
443
554
|
// show message after browsed book is expired.
|
|
444
555
|
this.loanRenewResult.renewNow = false;
|
|
445
556
|
this.loanRenewResult.texts =
|
|
446
|
-
'This book has been
|
|
557
|
+
'This book has been returned due to inactivity.';
|
|
447
558
|
|
|
448
|
-
this.
|
|
449
|
-
this.showToastMessage();
|
|
559
|
+
this.showExpiredModal();
|
|
450
560
|
|
|
451
561
|
window?.Sentry?.captureMessage(sentryLogs.browseHasExpired);
|
|
452
562
|
}
|
|
453
563
|
|
|
564
|
+
async startBrowseTimer() {
|
|
565
|
+
clearTimeout(this.browseTimer);
|
|
566
|
+
|
|
567
|
+
const {
|
|
568
|
+
browsingExpired,
|
|
569
|
+
user_has_browsed,
|
|
570
|
+
secondsLeftOnLoan,
|
|
571
|
+
} = this.lendingStatus;
|
|
572
|
+
if (!user_has_browsed || browsingExpired) {
|
|
573
|
+
console.log('user not browsed', this.lendingStatus);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
console.log('user browsed', this.lendingStatus);
|
|
578
|
+
|
|
579
|
+
this.browseTimer = setTimeout(() => {
|
|
580
|
+
this.browseHasExpired();
|
|
581
|
+
}, secondsLeftOnLoan * 1000);
|
|
582
|
+
}
|
|
583
|
+
|
|
454
584
|
/**
|
|
455
585
|
* Reset timer animation state after book renewed
|
|
456
586
|
*/
|
|
@@ -524,6 +654,7 @@ export default class IABookActions extends LitElement {
|
|
|
524
654
|
?disabled=${this.disableActionGroup}
|
|
525
655
|
?autoRenew=${this.loanRenewResult.renewNow}
|
|
526
656
|
?autoReturn=${this.lendingStatus.browsingExpired}
|
|
657
|
+
?returnNow=${this.returnNow}
|
|
527
658
|
@loanAutoRenewed=${this.handleLoanAutoRenewed}
|
|
528
659
|
@lendingActionError=${this.handleLendingActionError}
|
|
529
660
|
@toggleActionGroup=${this.handleToggleActionGroup}
|
|
@@ -545,19 +676,21 @@ export default class IABookActions extends LitElement {
|
|
|
545
676
|
if (this.loanRenewResult.renewNow) {
|
|
546
677
|
window?.IALendingIntervals?.clearAll();
|
|
547
678
|
|
|
548
|
-
this.suppressToast = false;
|
|
549
|
-
await this.browseHasRenew();
|
|
550
|
-
await this.showToastMessage();
|
|
551
|
-
await this.resetTimerCountState();
|
|
552
|
-
|
|
553
|
-
window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
|
|
554
|
-
|
|
555
679
|
// testing console....
|
|
556
680
|
console.log('IABookActions: AutoRenewed:- ', {
|
|
557
681
|
ajaxResponse: event?.detail?.data,
|
|
558
682
|
loanRenewResult: this.loanRenewResult,
|
|
559
683
|
secondsLeftOnLoan: Math.round(this.lendingStatus.secondsLeftOnLoan),
|
|
560
684
|
});
|
|
685
|
+
|
|
686
|
+
await this.browseHasRenew();
|
|
687
|
+
await this.resetTimerCountState();
|
|
688
|
+
|
|
689
|
+
// close the modal
|
|
690
|
+
this.modal?.remove();
|
|
691
|
+
this.modal?.showModal({ config: {}, customModalContent: `` });
|
|
692
|
+
|
|
693
|
+
window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
|
|
561
694
|
}
|
|
562
695
|
}
|
|
563
696
|
|
|
@@ -602,7 +735,7 @@ export default class IABookActions extends LitElement {
|
|
|
602
735
|
this.disableActionGroup = !this.disableActionGroup;
|
|
603
736
|
}
|
|
604
737
|
|
|
605
|
-
|
|
738
|
+
/**
|
|
606
739
|
* handle lending errors occure during different operation like
|
|
607
740
|
* browse book, borrow book, borrowed book token etc...
|
|
608
741
|
*
|
|
@@ -656,16 +789,7 @@ export default class IABookActions extends LitElement {
|
|
|
656
789
|
|
|
657
790
|
/* show error message if something went wrong */
|
|
658
791
|
async showErrorModal(errorMsg, action) {
|
|
659
|
-
|
|
660
|
-
if (!this.modal) {
|
|
661
|
-
this.modal = document.querySelector('modal-manager');
|
|
662
|
-
|
|
663
|
-
// check the DOM if <modal-manager> already there
|
|
664
|
-
if (!this.modal) this.modal = document.createElement('modal-manager');
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
this.modal.id = 'action-bar-modal';
|
|
668
|
-
await document.body.appendChild(this.modal);
|
|
792
|
+
await this.useModalManager();
|
|
669
793
|
|
|
670
794
|
const modalConfig = new ModalConfig({
|
|
671
795
|
title: 'Lending error',
|
|
@@ -676,7 +800,7 @@ export default class IABookActions extends LitElement {
|
|
|
676
800
|
|
|
677
801
|
if (action === 'create_token') {
|
|
678
802
|
const refreshButton = html`<button
|
|
679
|
-
style="
|
|
803
|
+
style="${modalButtonStyle.refresh}"
|
|
680
804
|
@click=${() => window.location.reload(true)}
|
|
681
805
|
>
|
|
682
806
|
refresh
|
|
@@ -188,7 +188,9 @@ describe('Borrow status actions', () => {
|
|
|
188
188
|
},
|
|
189
189
|
];
|
|
190
190
|
|
|
191
|
-
expect(el.primaryTitle).to.equal(
|
|
191
|
+
expect(el.primaryTitle).to.equal(
|
|
192
|
+
'Renews automatically as long as pages are turned.'
|
|
193
|
+
);
|
|
192
194
|
expect(el.primaryActions.length).to.equal(2);
|
|
193
195
|
expect(el.primaryActions[0].text).to.equal('Log In and Borrow');
|
|
194
196
|
expect(el.primaryActions[0].text).to.equal(expectedPrimaryActions[0].text);
|
|
@@ -274,7 +276,7 @@ describe('Browsing expired status', () => {
|
|
|
274
276
|
expect(el.loanRenewResult.renewNow).to.equal(false);
|
|
275
277
|
expect(el.loanRenewResult.secondsLeft).to.equal(0);
|
|
276
278
|
expect(el.loanRenewResult.texts).to.equal(
|
|
277
|
-
'This book has been
|
|
279
|
+
'This book has been returned due to inactivity.'
|
|
278
280
|
);
|
|
279
281
|
});
|
|
280
282
|
|
|
@@ -347,7 +349,7 @@ describe('Auto renew one hour loan', () => {
|
|
|
347
349
|
});
|
|
348
350
|
el.dispatchEvent(myEvent);
|
|
349
351
|
|
|
350
|
-
await aTimeout(
|
|
352
|
+
await aTimeout(1900); // wait for 1.9 second
|
|
351
353
|
await el.updateComplete;
|
|
352
354
|
|
|
353
355
|
expect(el.loanRenewResult.texts).to.equal(
|