@internetarchive/ia-book-actions 0.1.2 → 0.1.3-alpha2
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 +1 -1
- package/src/components/timer-countdown.js +18 -12
- package/src/core/config/ia-lending-intervals.js +35 -0
- package/src/core/services/loan-renew-helper.js +9 -2
- package/src/core/services/loan-token-poller.js +8 -14
- package/src/ia-book-actions.js +17 -12
- package/demo/with-bookreader.html +0 -146
package/package.json
CHANGED
|
@@ -31,12 +31,6 @@ export default class TimerCountdown extends LitElement {
|
|
|
31
31
|
*/
|
|
32
32
|
this.loanRenewAtLast = 0;
|
|
33
33
|
|
|
34
|
-
/**
|
|
35
|
-
* setInterval executed interval
|
|
36
|
-
* @type {number}
|
|
37
|
-
*/
|
|
38
|
-
this.timerInterval = undefined;
|
|
39
|
-
|
|
40
34
|
/**
|
|
41
35
|
* delay seconds in setInterval function
|
|
42
36
|
* @type {number}
|
|
@@ -45,12 +39,13 @@ export default class TimerCountdown extends LitElement {
|
|
|
45
39
|
}
|
|
46
40
|
|
|
47
41
|
disconnectedCallback() {
|
|
48
|
-
|
|
42
|
+
window?.IALendingIntervals?.clearTimerCountdown();
|
|
49
43
|
}
|
|
50
44
|
|
|
51
45
|
updated(changed) {
|
|
52
46
|
if (changed.has('secondsLeftOnLoan') && this.secondsLeftOnLoan > 0) {
|
|
53
|
-
|
|
47
|
+
this.disconnectedCallback();
|
|
48
|
+
|
|
54
49
|
this.timerCountdown();
|
|
55
50
|
}
|
|
56
51
|
}
|
|
@@ -59,10 +54,21 @@ export default class TimerCountdown extends LitElement {
|
|
|
59
54
|
// - let just execute setInterval in every 1 minute
|
|
60
55
|
this.timerExecutionSeconds = 60;
|
|
61
56
|
|
|
62
|
-
|
|
57
|
+
/**
|
|
58
|
+
* set interval in window object
|
|
59
|
+
* @see ia-lending-intervals.js
|
|
60
|
+
*/
|
|
61
|
+
window.IALendingIntervals.timerCountdown = setInterval(() => {
|
|
63
62
|
this.secondsLeftOnLoan -= this.timerExecutionSeconds;
|
|
64
63
|
const secondsLeft = Math.round(this.secondsLeftOnLoan);
|
|
65
64
|
|
|
65
|
+
console.log(
|
|
66
|
+
'timeLeftInSec',
|
|
67
|
+
secondsLeft,
|
|
68
|
+
' ||| timeLeftInMin',
|
|
69
|
+
Math.ceil(secondsLeft / 60)
|
|
70
|
+
);
|
|
71
|
+
|
|
66
72
|
/**
|
|
67
73
|
* execute from last 10th minute to 0th minute
|
|
68
74
|
* - 10th - to check if user has viewed
|
|
@@ -84,7 +90,7 @@ export default class TimerCountdown extends LitElement {
|
|
|
84
90
|
|
|
85
91
|
// clear interval
|
|
86
92
|
if (secondsLeft <= 60) {
|
|
87
|
-
|
|
93
|
+
this.disconnectedCallback();
|
|
88
94
|
window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
|
|
89
95
|
}
|
|
90
96
|
}, this.timerExecutionSeconds * 1000);
|
|
@@ -111,8 +117,8 @@ export default class TimerCountdown extends LitElement {
|
|
|
111
117
|
render() {
|
|
112
118
|
return html`
|
|
113
119
|
<svg
|
|
114
|
-
width="
|
|
115
|
-
height="
|
|
120
|
+
width="14"
|
|
121
|
+
height="14"
|
|
116
122
|
viewBox="0 0 100 100"
|
|
117
123
|
xmlns="http://www.w3.org/2000/svg"
|
|
118
124
|
>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection of methods for managing intervals for lending system
|
|
3
|
+
*
|
|
4
|
+
* There are mainly two intervals being used
|
|
5
|
+
* - tokenPoller :- used to create_token for borrowed book
|
|
6
|
+
* - timerCountdown :- reponsible for loan-auto-renew and auto returned warning message
|
|
7
|
+
*
|
|
8
|
+
* @see TimerCountdown::timerCountdown function
|
|
9
|
+
* @see LoanTokenPoller::bookAccessed function
|
|
10
|
+
*
|
|
11
|
+
* @type {Object}
|
|
12
|
+
*/
|
|
13
|
+
window.IALendingIntervals = {
|
|
14
|
+
/**
|
|
15
|
+
* clear interval for create_token api
|
|
16
|
+
*/
|
|
17
|
+
clearTokenPoller: () => {
|
|
18
|
+
window.clearInterval(window?.IALendingIntervals?.tokenPoller);
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* clear interval for graphic timer for one-hour loan renew
|
|
23
|
+
*/
|
|
24
|
+
clearTimerCountdown: () => {
|
|
25
|
+
window.clearInterval(window.IALendingIntervals.timerCountdown);
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* clear all intervals being used acros lending system
|
|
30
|
+
*/
|
|
31
|
+
clearAll: () => {
|
|
32
|
+
window.clearInterval(window?.IALendingIntervals?.tokenPoller);
|
|
33
|
+
window.clearInterval(window?.IALendingIntervals?.timerCountdown);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -13,7 +13,8 @@ export class LoanRenewHelper {
|
|
|
13
13
|
this.loanRenewTimeConfig = loanRenewTimeConfig;
|
|
14
14
|
|
|
15
15
|
// messages for auto return machenism
|
|
16
|
-
this.loanRenewMessage =
|
|
16
|
+
this.loanRenewMessage =
|
|
17
|
+
'This book has been renewed for #time #unitsOfTime.';
|
|
17
18
|
this.loanReturnWarning =
|
|
18
19
|
'This book will be automatically returned in #time #unitsOfTime unless you turn a page.';
|
|
19
20
|
|
|
@@ -117,7 +118,7 @@ export class LoanRenewHelper {
|
|
|
117
118
|
* @returns {String} // texts will be appear in toast template
|
|
118
119
|
*/
|
|
119
120
|
getMessageTexts(texts, secondsLeft) {
|
|
120
|
-
|
|
121
|
+
let unitOfTime = 'minute';
|
|
121
122
|
|
|
122
123
|
let toastTexts = texts;
|
|
123
124
|
let timeLeft = secondsLeft;
|
|
@@ -125,6 +126,12 @@ export class LoanRenewHelper {
|
|
|
125
126
|
// convert time from second to minute
|
|
126
127
|
timeLeft = Math.ceil(timeLeft / 60);
|
|
127
128
|
|
|
129
|
+
// convert time from minute to hour
|
|
130
|
+
if (timeLeft > 59) {
|
|
131
|
+
timeLeft = 1; // 1 hour
|
|
132
|
+
unitOfTime = 'hour';
|
|
133
|
+
}
|
|
134
|
+
|
|
128
135
|
// replace #time variable with remaining time
|
|
129
136
|
toastTexts = toastTexts?.replace(/#time/, timeLeft);
|
|
130
137
|
|
|
@@ -20,17 +20,8 @@ export class LoanTokenPoller {
|
|
|
20
20
|
this.bookAccessed();
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.loanTokenInterval = undefined;
|
|
26
|
-
|
|
27
|
-
// temporary disabling sentry notice
|
|
28
|
-
// as message is informational, not critical nor an error.
|
|
29
|
-
// also, as of 11/28/2022, JS build maps are not working properly on petabox
|
|
30
|
-
// and as a result, this comment is not properly grouped.
|
|
31
|
-
// if (window.Sentry) {
|
|
32
|
-
// window?.Sentry?.captureMessage('loan token interval cleared');
|
|
33
|
-
// }
|
|
23
|
+
disconnectedCallback() {
|
|
24
|
+
window?.IALendingIntervals?.clearTokenPoller();
|
|
34
25
|
}
|
|
35
26
|
|
|
36
27
|
async bookAccessed() {
|
|
@@ -59,7 +50,11 @@ export class LoanTokenPoller {
|
|
|
59
50
|
// - we don't want to fetch token on interval
|
|
60
51
|
// - the initial token is enough to set cookies for reading book and readaloud features
|
|
61
52
|
if (this.borrowType !== 'adminBorrowed') {
|
|
62
|
-
|
|
53
|
+
/**
|
|
54
|
+
* set interval in window object
|
|
55
|
+
* @see ia-lending-intervals.js
|
|
56
|
+
*/
|
|
57
|
+
window.IALendingIntervals.tokenPoller = setInterval(() => {
|
|
63
58
|
this.handleLoanTokenPoller();
|
|
64
59
|
}, this.pollerDelay * 1000);
|
|
65
60
|
}
|
|
@@ -77,7 +72,7 @@ export class LoanTokenPoller {
|
|
|
77
72
|
);
|
|
78
73
|
|
|
79
74
|
// if book is not browsed, just clear token polling interval
|
|
80
|
-
this.
|
|
75
|
+
this.disconnectedCallback();
|
|
81
76
|
}
|
|
82
77
|
}
|
|
83
78
|
|
|
@@ -95,7 +90,6 @@ export class LoanTokenPoller {
|
|
|
95
90
|
identifier: this.identifier,
|
|
96
91
|
action,
|
|
97
92
|
error: data => {
|
|
98
|
-
this.disconnectedInterval(); // stop token fetch api
|
|
99
93
|
this.errorCallback({ detail: { action, data } });
|
|
100
94
|
|
|
101
95
|
// send error to Sentry
|
package/src/ia-book-actions.js
CHANGED
|
@@ -11,6 +11,7 @@ import './components/book-title-bar.js';
|
|
|
11
11
|
import './components/text-group.js';
|
|
12
12
|
import './components/info-icon.js';
|
|
13
13
|
import './components/timer-countdown.js';
|
|
14
|
+
import './core/config/ia-lending-intervals.js';
|
|
14
15
|
|
|
15
16
|
import { GetLendingActions } from './core/services/get-lending-actions.js';
|
|
16
17
|
import { mobileContainerWidth } from './core/config/constants.js';
|
|
@@ -102,7 +103,9 @@ export default class IABookActions extends LitElement {
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
disconnectedCallback() {
|
|
105
|
-
|
|
106
|
+
// clear all intervals for lending system
|
|
107
|
+
window?.IALendingIntervals?.clearAll();
|
|
108
|
+
|
|
106
109
|
window?.Sentry?.captureMessage(sentryLogs.disconnectedCallback);
|
|
107
110
|
this.disconnectResizeObserver();
|
|
108
111
|
}
|
|
@@ -197,7 +200,8 @@ export default class IABookActions extends LitElement {
|
|
|
197
200
|
if (!this.tokenPoller) {
|
|
198
201
|
window?.Sentry?.captureMessage(sentryLogs.bookWasExpired);
|
|
199
202
|
}
|
|
200
|
-
|
|
203
|
+
window?.IALendingIntervals?.clearAll();
|
|
204
|
+
|
|
201
205
|
/** Global event - always fire */
|
|
202
206
|
this.dispatchEvent(
|
|
203
207
|
new Event(events.browseExpired, {
|
|
@@ -336,7 +340,11 @@ export default class IABookActions extends LitElement {
|
|
|
336
340
|
|
|
337
341
|
// if secondsLeft < 60, consider it 1 minute
|
|
338
342
|
let { secondsLeft } = this.loanRenewResult;
|
|
339
|
-
|
|
343
|
+
if (secondsLeft === undefined) {
|
|
344
|
+
secondsLeft = this.lendingStatus.secondsLeftOnLoan;
|
|
345
|
+
} else {
|
|
346
|
+
secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
|
|
347
|
+
}
|
|
340
348
|
|
|
341
349
|
const config = new ToastConfig();
|
|
342
350
|
config.dismisOnClick = true;
|
|
@@ -385,7 +393,7 @@ export default class IABookActions extends LitElement {
|
|
|
385
393
|
* Execute when loan is expired
|
|
386
394
|
*/
|
|
387
395
|
async browseHasExpired() {
|
|
388
|
-
|
|
396
|
+
window?.IALendingIntervals?.clearAll();
|
|
389
397
|
|
|
390
398
|
const currStatus = { ...this.lendingStatus, browsingExpired: true };
|
|
391
399
|
this.lendingStatus = currStatus;
|
|
@@ -495,11 +503,11 @@ export default class IABookActions extends LitElement {
|
|
|
495
503
|
*/
|
|
496
504
|
async handleLoanAutoRenewed() {
|
|
497
505
|
if (this.loanRenewResult.renewNow) {
|
|
498
|
-
|
|
506
|
+
window?.IALendingIntervals?.clearAll();
|
|
499
507
|
|
|
500
508
|
this.suppressToast = false;
|
|
501
|
-
await this.showToastMessage();
|
|
502
509
|
await this.browseHasRenew();
|
|
510
|
+
await this.showToastMessage();
|
|
503
511
|
await this.resetTimerCountState();
|
|
504
512
|
|
|
505
513
|
window?.Sentry?.captureMessage(`${sentryLogs.bookHasRenewed}`);
|
|
@@ -519,10 +527,6 @@ export default class IABookActions extends LitElement {
|
|
|
519
527
|
* @see LoanTokenPoller
|
|
520
528
|
*/
|
|
521
529
|
startLoanTokenPoller() {
|
|
522
|
-
if (this.tokenPoller) {
|
|
523
|
-
window?.Sentry?.captureMessage(sentryLogs.clearTokenPoller);
|
|
524
|
-
this.tokenPoller?.disconnectedInterval();
|
|
525
|
-
}
|
|
526
530
|
const successCallback = () => {
|
|
527
531
|
this.lendingBarPostInit();
|
|
528
532
|
};
|
|
@@ -572,6 +576,9 @@ export default class IABookActions extends LitElement {
|
|
|
572
576
|
// toggle activity loader
|
|
573
577
|
this.handleToggleActionGroup();
|
|
574
578
|
|
|
579
|
+
// clear all intervals for lending system when error occured
|
|
580
|
+
window?.IALendingIntervals?.clearAll();
|
|
581
|
+
|
|
575
582
|
const action = event?.detail?.action;
|
|
576
583
|
const errorMsg = event?.detail?.data?.error;
|
|
577
584
|
|
|
@@ -581,8 +588,6 @@ export default class IABookActions extends LitElement {
|
|
|
581
588
|
// - clear tokenPoller interval
|
|
582
589
|
// - set user_has_browsed to `false`
|
|
583
590
|
if (action === 'create_token') {
|
|
584
|
-
this.tokenPoller?.disconnectedInterval();
|
|
585
|
-
|
|
586
591
|
const currStatus = {
|
|
587
592
|
...this.lendingStatus,
|
|
588
593
|
user_has_browsed: false,
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en-GB">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="utf-8">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
7
|
-
<style>
|
|
8
|
-
html {
|
|
9
|
-
font-size: 10px;
|
|
10
|
-
/* This is to match petabox's base font size */
|
|
11
|
-
}
|
|
12
|
-
body {
|
|
13
|
-
margin: 0;
|
|
14
|
-
text-align: center;
|
|
15
|
-
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
16
|
-
}
|
|
17
|
-
#demo {
|
|
18
|
-
height: 50px;
|
|
19
|
-
}
|
|
20
|
-
ia-book-actions {
|
|
21
|
-
--white: #fff;
|
|
22
|
-
--black: #000;
|
|
23
|
-
--primaryBGColor: var(--black);
|
|
24
|
-
--secondaryBGColor: #222;
|
|
25
|
-
--tertiaryBGColor: #333;
|
|
26
|
-
--primaryTextColor: var(--white);
|
|
27
|
-
--primaryCTAFill: #194880;
|
|
28
|
-
--primaryCTABorder: #c5d1df;
|
|
29
|
-
--secondaryCTAFill: #333;
|
|
30
|
-
--secondaryCTABorder: #999;
|
|
31
|
-
--secondaryCTAFillRGB: 51, 51, 51;
|
|
32
|
-
--primaryErrorCTAFill: #e51c26;
|
|
33
|
-
--primaryErrorCTABorder: #f8c6c8;
|
|
34
|
-
--primaryCTAFillRGB: 25, 72, 128;
|
|
35
|
-
--primaryErrorCTAFillRGB: 229, 28, 38;
|
|
36
|
-
--primaryDisableCTAFill: #767676;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
fieldset {
|
|
40
|
-
width: fit-content;
|
|
41
|
-
margin-top: 50px;
|
|
42
|
-
}
|
|
43
|
-
fieldset legend {
|
|
44
|
-
text-align: left;
|
|
45
|
-
font-size: 12px;
|
|
46
|
-
}
|
|
47
|
-
td {
|
|
48
|
-
color: white;
|
|
49
|
-
font-size: 14px;
|
|
50
|
-
border-radius: 5%;
|
|
51
|
-
display: table-cell;
|
|
52
|
-
text-align: initial;
|
|
53
|
-
margin: 5px 0;
|
|
54
|
-
width: max-content;
|
|
55
|
-
display: block;
|
|
56
|
-
}
|
|
57
|
-
label {
|
|
58
|
-
padding: 10px;
|
|
59
|
-
display: block;
|
|
60
|
-
cursor: pointer;
|
|
61
|
-
margin: 2px;
|
|
62
|
-
background: #4e545a;
|
|
63
|
-
border-radius: 10px;
|
|
64
|
-
}
|
|
65
|
-
input[type="radio"], input[type="checkbox"] {
|
|
66
|
-
margin-top: 0;
|
|
67
|
-
vertical-align: middle;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.initial td {
|
|
71
|
-
float: left;
|
|
72
|
-
margin: 2px;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
body.modal-manager-open {
|
|
76
|
-
overflow: hidden;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
modal-manager[mode='closed'] {
|
|
80
|
-
display: none;
|
|
81
|
-
}
|
|
82
|
-
</style>
|
|
83
|
-
</head>
|
|
84
|
-
|
|
85
|
-
<body>
|
|
86
|
-
<ia-bookreader class="focus-on-child-only" signedin="" fullscreen="">
|
|
87
|
-
<div slot="header">
|
|
88
|
-
<ia-book-actions></ia-book-actions>
|
|
89
|
-
</div>
|
|
90
|
-
<div slot="main">
|
|
91
|
-
<div id="BookReader"></div>
|
|
92
|
-
</div>
|
|
93
|
-
</ia-bookreader>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<script type="module">
|
|
97
|
-
/* eslint-disable */
|
|
98
|
-
import '@internetarchive/bookreader';
|
|
99
|
-
import '@internetarchive/bookreader/BookReader/jquery-1.10.1.js';
|
|
100
|
-
import '@internetarchive/bookreader/BookReader/BookReader.js';
|
|
101
|
-
import '../src/ia-book-actions.js';
|
|
102
|
-
import {
|
|
103
|
-
defaultLendingStatus,
|
|
104
|
-
canBrowseAndBorrow,
|
|
105
|
-
} from '../src/assets/data/lending-get-status-service.js';
|
|
106
|
-
import { ModalConfig } from '@internetarchive/modal-manager';
|
|
107
|
-
|
|
108
|
-
const userid = '@neeraj-archive';
|
|
109
|
-
const identifier = 'naturalhistoryof00unse_4111';
|
|
110
|
-
let bwbPurchaseUrl = 'https://www.betterworldbooks.com/product/detail/cambridge-ancient-hist-v04-0521044863';
|
|
111
|
-
|
|
112
|
-
let iaBookActions = document.querySelector('ia-book-actions');
|
|
113
|
-
|
|
114
|
-
// for debugging
|
|
115
|
-
window.iaBookActions = iaBookActions;
|
|
116
|
-
|
|
117
|
-
const modalConfig = new ModalConfig();
|
|
118
|
-
modalConfig.headerColor = '#d9534f';
|
|
119
|
-
|
|
120
|
-
let lendingBarPostInit = function lendingBarPostInit() {
|
|
121
|
-
setTimeout(function() {
|
|
122
|
-
console.log('executed', 'br.init()');
|
|
123
|
-
}, 100);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
127
|
-
iaBookActions.userid = userid;
|
|
128
|
-
iaBookActions.identifier = identifier;
|
|
129
|
-
iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
|
|
130
|
-
iaBookActions.lendingStatus = canBrowseAndBorrow;
|
|
131
|
-
iaBookActions.bwbPurchaseUrl = '';
|
|
132
|
-
iaBookActions.modalConfig = modalConfig;
|
|
133
|
-
iaBookActions.lendingBarPostInit = lendingBarPostInit;
|
|
134
|
-
iaBookActions.tokenDelay = 2000; // 2 seconds
|
|
135
|
-
iaBookActions.returnUrl = 'https://openlibrary.org';
|
|
136
|
-
|
|
137
|
-
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
138
|
-
|
|
139
|
-
const manifest = await fetch('https://ia801302.us.archive.org/BookReader/BookReaderJSIA.php?id=goody&itemPath=/29/items/goody&server=ia801302.us.archive.org&format=jsonp&subPrefix=goody&requestUri=/details/goody/mode/1up%3Fview%3Dtheater%26ui%3Dembed%26wrapper%3Dfalse');
|
|
140
|
-
|
|
141
|
-
console.log('manifest ****', manifest).then(res => res.json());
|
|
142
|
-
</script>
|
|
143
|
-
|
|
144
|
-
</div>
|
|
145
|
-
</body>
|
|
146
|
-
</html>
|