@internetarchive/ia-book-actions 0.0.29-alpha39 → 0.0.29-alpha40
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/demo/index.html +6 -5
- package/package.json +10 -8
- package/src/components/timer-countdown.js +55 -38
- package/src/core/config/sentry-events.js +2 -2
- package/src/core/services/actions-config.js +2 -2
- package/src/core/services/actions-handler/actions-handler.js +11 -6
- package/src/core/services/loan-renew-helper.js +13 -13
- package/src/core/services/loan-token-poller.js +3 -3
- package/src/ia-book-actions.js +49 -36
- package/test/components/timer-countdown.test.js +12 -12
- package/test/core/services/loan-renew-helper.test.js +13 -11
- package/test/ia-book-actions.test.js +6 -6
package/demo/index.html
CHANGED
|
@@ -120,6 +120,7 @@
|
|
|
120
120
|
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
121
121
|
let iaBookActions = document.querySelector('ia-book-actions');
|
|
122
122
|
|
|
123
|
+
|
|
123
124
|
iaBookActions.userid = userid;
|
|
124
125
|
iaBookActions.identifier = identifier;
|
|
125
126
|
iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
|
|
@@ -132,15 +133,15 @@
|
|
|
132
133
|
iaBookActions.localCache = localCache;
|
|
133
134
|
|
|
134
135
|
let isDevBox = true;
|
|
135
|
-
iaBookActions.
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
iaBookActions.loanRenewTimeConfig = {
|
|
137
|
+
loanTotalTime: isDevBox ? 13 : 3600, // 60 second = 1 min
|
|
138
|
+
loanRenewAtLast: isDevBox ? 10 : 3540, // at last 10th minute
|
|
138
139
|
pageChangedInLast: isDevBox ? 5 : 900, // within last 15 second/minute
|
|
139
140
|
isDevBox: isDevBox,
|
|
140
141
|
};
|
|
141
142
|
|
|
142
143
|
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
143
|
-
let secondsLeftOnLoan = iaBookActions.
|
|
144
|
+
let secondsLeftOnLoan = iaBookActions.loanRenewTimeConfig.loanTotalTime;
|
|
144
145
|
|
|
145
146
|
document.querySelectorAll('.titleBar input[type=checkbox]').forEach((item) => {
|
|
146
147
|
item.addEventListener('click', (e) => {
|
|
@@ -217,7 +218,7 @@
|
|
|
217
218
|
await localCache.set({
|
|
218
219
|
key: `${identifier}-loanTime`,
|
|
219
220
|
value: new Date(), // current time
|
|
220
|
-
ttl: Number(iaBookActions.
|
|
221
|
+
ttl: Number(iaBookActions.loanRenewTimeConfig.loanTotalTime),
|
|
221
222
|
});
|
|
222
223
|
|
|
223
224
|
await localCache.delete(`${identifier}-pageChangedTime`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "0.0.29-
|
|
3
|
+
"version": "0.0.29-alpha40",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@internetarchive/icon-info": "^1.2.6",
|
|
22
22
|
"@internetarchive/local-cache": "^0.2.0",
|
|
23
|
-
"@internetarchive/modal-manager": "^0.2.
|
|
23
|
+
"@internetarchive/modal-manager": "^0.2.8",
|
|
24
24
|
"@internetarchive/shared-resize-observer": "^0.2.0",
|
|
25
|
-
"@internetarchive/toast-manager": "0.0
|
|
25
|
+
"@internetarchive/toast-manager": "0.1.0",
|
|
26
26
|
"lit": "^2.5.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
},
|
|
46
46
|
"eslintConfig": {
|
|
47
47
|
"rules": {
|
|
48
|
-
"no-console": "
|
|
49
|
-
"no-unused-expressions": "
|
|
50
|
-
"class-methods-use-this": "
|
|
51
|
-
"lit-a11y/click-events-have-key-events": "
|
|
48
|
+
"no-console": "warn",
|
|
49
|
+
"no-unused-expressions": "warn",
|
|
50
|
+
"class-methods-use-this": "warn",
|
|
51
|
+
"lit-a11y/click-events-have-key-events": "warn"
|
|
52
52
|
},
|
|
53
53
|
"extends": [
|
|
54
54
|
"@open-wc/eslint-config",
|
|
@@ -60,7 +60,9 @@
|
|
|
60
60
|
"arrowParens": "avoid"
|
|
61
61
|
},
|
|
62
62
|
"husky": {
|
|
63
|
-
"hooks": {
|
|
63
|
+
"hooks": {
|
|
64
|
+
"pre-commit": "lint-staged"
|
|
65
|
+
}
|
|
64
66
|
},
|
|
65
67
|
"lint-staged": {
|
|
66
68
|
"*.js": [
|
|
@@ -4,15 +4,31 @@ import { sentryLogs } from '../core/config/sentry-events.js';
|
|
|
4
4
|
export default class TimerCountdown extends LitElement {
|
|
5
5
|
static get properties() {
|
|
6
6
|
return {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
secondsLeftOnLoan: { type: Number }, // in seconds
|
|
8
|
+
loanRenewAtLast: { type: Number }, // in seconds
|
|
9
|
+
isDevBox: { type: Boolean },
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
constructor() {
|
|
13
14
|
super();
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* seconds left in current time
|
|
18
|
+
* @type {number}
|
|
19
|
+
*/
|
|
20
|
+
this.secondsLeftOnLoan = 0;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* at the remaining time, we attempt to renew current loan
|
|
24
|
+
* @type {number}
|
|
25
|
+
*/
|
|
26
|
+
this.loanRenewAtLast = 0;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @type {boolean}
|
|
30
|
+
*/
|
|
31
|
+
this.isDevBox = false;
|
|
16
32
|
|
|
17
33
|
// private props
|
|
18
34
|
this.timerInterval = undefined;
|
|
@@ -23,44 +39,44 @@ export default class TimerCountdown extends LitElement {
|
|
|
23
39
|
}
|
|
24
40
|
|
|
25
41
|
updated(changed) {
|
|
26
|
-
if (changed.has('
|
|
42
|
+
if (changed.has('secondsLeftOnLoan') && this.secondsLeftOnLoan > 0) {
|
|
27
43
|
clearInterval(this.timerInterval);
|
|
28
44
|
this.timerCountdown();
|
|
29
45
|
}
|
|
30
46
|
}
|
|
31
47
|
|
|
32
48
|
timerCountdown() {
|
|
33
|
-
// execute
|
|
34
|
-
this.
|
|
35
|
-
() => {
|
|
36
|
-
this.timeLeftOnLoan -= this.loanRenewConfig.isDevBox ? 1 : 60;
|
|
37
|
-
const timeLeft = Math.round(this.timeLeftOnLoan);
|
|
38
|
-
|
|
39
|
-
// execute from last 10th minute to 0th minute
|
|
40
|
-
// - 10th - to check if user has viewed
|
|
41
|
-
// - till 0th - to show warning msg with remaining time to auto returned
|
|
42
|
-
if (timeLeft <= this.loanRenewConfig.autoCheckAt) {
|
|
43
|
-
this.dispatchEvent(
|
|
44
|
-
new CustomEvent('IABookActions:loanRenew', {
|
|
45
|
-
detail: {
|
|
46
|
-
hasPageChanged: false,
|
|
47
|
-
timeLeft,
|
|
48
|
-
},
|
|
49
|
-
bubbles: true,
|
|
50
|
-
composed: true,
|
|
51
|
-
})
|
|
52
|
-
);
|
|
53
|
-
}
|
|
49
|
+
// in-case of isDevBox, execute timer in each second instead of 60
|
|
50
|
+
const timerIntervalSeconds = this.isDevBox ? 1 : 60;
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
this.timerInterval = setInterval(() => {
|
|
53
|
+
// if this.isDevBox, just reduce seconds by 1 instead of 60 (1 min)
|
|
54
|
+
this.secondsLeftOnLoan -= timerIntervalSeconds;
|
|
55
|
+
const secondsLeft = Math.round(this.secondsLeftOnLoan);
|
|
56
|
+
|
|
57
|
+
// execute from last 10th minute to 0th minute
|
|
58
|
+
// - 10th - to check if user has viewed
|
|
59
|
+
// - till 0th - to show warning msg with remaining time to auto expired
|
|
60
|
+
if (secondsLeft <= this.loanRenewAtLast) {
|
|
61
|
+
this.dispatchEvent(
|
|
62
|
+
new CustomEvent('IABookActions:loanRenew', {
|
|
63
|
+
detail: {
|
|
64
|
+
hasPageChanged: false,
|
|
65
|
+
secondsLeft,
|
|
66
|
+
},
|
|
67
|
+
bubbles: true,
|
|
68
|
+
composed: true,
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// clear interval
|
|
74
|
+
if (secondsLeft <= 1) {
|
|
75
|
+
clearInterval(this.timerInterval);
|
|
76
|
+
window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
|
|
77
|
+
console.log(sentryLogs.clearOneHourTimer);
|
|
78
|
+
}
|
|
79
|
+
}, timerIntervalSeconds * 1000);
|
|
64
80
|
}
|
|
65
81
|
|
|
66
82
|
render() {
|
|
@@ -73,14 +89,15 @@ export default class TimerCountdown extends LitElement {
|
|
|
73
89
|
>
|
|
74
90
|
<circle class="circle" cx="50" cy="50" r="50" />
|
|
75
91
|
</svg>
|
|
76
|
-
<span
|
|
92
|
+
<span class="sr-only"></span>
|
|
93
|
+
<span>${Math.round(this.secondsLeftOnLoan)}</span>
|
|
77
94
|
`;
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
static get styles() {
|
|
81
98
|
const white = css`var(--white, #fff)`;
|
|
82
|
-
const timerSecondsLeft = css`var(--
|
|
83
|
-
const timerStrokeLeft = css`var(--
|
|
99
|
+
const timerSecondsLeft = css`var(--secondsLeftOnLoan, 6000s)`; //
|
|
100
|
+
const timerStrokeLeft = css`var(--strokeLeftOnLoan, 315)`;
|
|
84
101
|
|
|
85
102
|
return css`
|
|
86
103
|
:host {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* sentry logs/messages we send for different actions....
|
|
3
3
|
*/
|
|
4
4
|
export const sentryLogs = {
|
|
5
5
|
disconnectedCallback: 'IABookActions:disconnectedCallback',
|
|
@@ -13,7 +13,7 @@ export const sentryLogs = {
|
|
|
13
13
|
'IABookActions:startLoanTokenPoller - clearing token poller interval',
|
|
14
14
|
clearOneHourTimer:
|
|
15
15
|
'IABookActions:timerCountdown - one-hour timer interval cleared',
|
|
16
|
-
|
|
16
|
+
bookAccessed: 'IABookActions:bookAccessed',
|
|
17
17
|
handleLoanTokenPoller: 'IABookActions:handleLoanTokenPoller',
|
|
18
18
|
setConsecutiveLoanCounts: 'IABookActions:setConsecutiveLoanCounts',
|
|
19
19
|
actionsHandlerService: 'IABookActions:actionsHandlerService',
|
|
@@ -36,7 +36,7 @@ export default class ActionsConfig {
|
|
|
36
36
|
firstBrowseConfig() {
|
|
37
37
|
return {
|
|
38
38
|
id: 'browseBook',
|
|
39
|
-
text: 'Borrow',
|
|
39
|
+
text: 'Borrow',
|
|
40
40
|
className: 'primary',
|
|
41
41
|
analyticsEvent: {
|
|
42
42
|
category: this.analyticsCategories.preview,
|
|
@@ -48,7 +48,7 @@ export default class ActionsConfig {
|
|
|
48
48
|
browseAgainConfig() {
|
|
49
49
|
return {
|
|
50
50
|
id: 'browseBookAgain',
|
|
51
|
-
text: 'Borrow',
|
|
51
|
+
text: 'Borrow',
|
|
52
52
|
className: 'primary',
|
|
53
53
|
analyticsEvent: {
|
|
54
54
|
category: this.analyticsCategories.browse,
|
|
@@ -17,7 +17,12 @@ import * as Cookies from '../doc-cookies.js';
|
|
|
17
17
|
export default class ActionsHandler extends LitElement {
|
|
18
18
|
constructor() {
|
|
19
19
|
super();
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* wait untill borrow is complete, then refresh the page
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
this.waitUntillBorrowComplete = 6; // in seconds
|
|
21
26
|
|
|
22
27
|
this.bindEvents();
|
|
23
28
|
}
|
|
@@ -126,7 +131,6 @@ export default class ActionsHandler extends LitElement {
|
|
|
126
131
|
action,
|
|
127
132
|
identifier: this.identifier,
|
|
128
133
|
success: data => {
|
|
129
|
-
// success analytics by isa?
|
|
130
134
|
this.setBrowseTimeSession();
|
|
131
135
|
this.dispatchEvent(
|
|
132
136
|
new CustomEvent('loanAutoRenewed', {
|
|
@@ -264,7 +268,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
264
268
|
// redirection on details page after 5 seconds because borrowing book takes time to create item creation.
|
|
265
269
|
setTimeout(() => {
|
|
266
270
|
URLHelper.goToUrl(redirectTo, true);
|
|
267
|
-
}, this.
|
|
271
|
+
}, this.waitUntillBorrowComplete * 1000);
|
|
268
272
|
}
|
|
269
273
|
|
|
270
274
|
// save consecutive loan count for borrow
|
|
@@ -297,14 +301,15 @@ export default class ActionsHandler extends LitElement {
|
|
|
297
301
|
*/
|
|
298
302
|
async setBrowseTimeSession() {
|
|
299
303
|
try {
|
|
300
|
-
const
|
|
301
|
-
|
|
304
|
+
const expireDate = new Date(
|
|
305
|
+
new Date().getTime() + this.loanTotalTime * 1000
|
|
306
|
+
);
|
|
302
307
|
|
|
303
308
|
// set a value
|
|
304
309
|
await this.localCache.set({
|
|
305
310
|
key: `${this.identifier}-loanTime`,
|
|
306
311
|
value: expireDate,
|
|
307
|
-
ttl: Number(
|
|
312
|
+
ttl: Number(this.loanTotalTime),
|
|
308
313
|
});
|
|
309
314
|
|
|
310
315
|
// delete pageChangedTime when book is auto renew at nth minute
|
|
@@ -4,11 +4,11 @@ import { nothing } from 'lit';
|
|
|
4
4
|
* This class is used to determine if use is eligible for auto renew loan.
|
|
5
5
|
*/
|
|
6
6
|
export class LoanRenewHelper {
|
|
7
|
-
constructor(hasPageChanged, identifier, localCache,
|
|
7
|
+
constructor(hasPageChanged, identifier, localCache, loanRenewTimeConfig) {
|
|
8
8
|
this.hasPageChanged = hasPageChanged;
|
|
9
9
|
this.identifier = identifier;
|
|
10
10
|
this.localCache = localCache;
|
|
11
|
-
this.
|
|
11
|
+
this.loanRenewTimeConfig = loanRenewTimeConfig;
|
|
12
12
|
|
|
13
13
|
// messages for auto return machenism
|
|
14
14
|
this.loanRenewMessage = 'This book has been renewed for 1 hour.';
|
|
@@ -44,15 +44,15 @@ export class LoanRenewHelper {
|
|
|
44
44
|
*/
|
|
45
45
|
async pageChanged() {
|
|
46
46
|
const {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
} = this.
|
|
47
|
+
loanTotalTime, // 60
|
|
48
|
+
loanRenewAtLast, // 50
|
|
49
|
+
} = this.loanRenewTimeConfig;
|
|
50
50
|
const currentTime = new Date();
|
|
51
51
|
const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
|
|
52
52
|
|
|
53
53
|
const lastTimeFrame = this.changeTime(
|
|
54
54
|
loanTime,
|
|
55
|
-
|
|
55
|
+
loanTotalTime - loanRenewAtLast,
|
|
56
56
|
'add'
|
|
57
57
|
);
|
|
58
58
|
|
|
@@ -74,7 +74,7 @@ export class LoanRenewHelper {
|
|
|
74
74
|
* @returns {this.result}
|
|
75
75
|
*/
|
|
76
76
|
async autoChecker() {
|
|
77
|
-
const { pageChangedInLast } = this.
|
|
77
|
+
const { pageChangedInLast } = this.loanRenewTimeConfig;
|
|
78
78
|
const pageChangedTime = await this.localCache.get(
|
|
79
79
|
`${this.identifier}-pageChangedTime`
|
|
80
80
|
);
|
|
@@ -108,7 +108,7 @@ export class LoanRenewHelper {
|
|
|
108
108
|
await this.localCache.set({
|
|
109
109
|
key: `${this.identifier}-pageChangedTime`,
|
|
110
110
|
value: new Date(), // current time
|
|
111
|
-
ttl: Number(this.
|
|
111
|
+
ttl: Number(this.loanRenewTimeConfig.loanTotalTime),
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -146,18 +146,18 @@ export class LoanRenewHelper {
|
|
|
146
146
|
* Helper function to get time difference
|
|
147
147
|
*
|
|
148
148
|
* @param {Date} date
|
|
149
|
-
* @param {Number}
|
|
150
|
-
* @param {String} op
|
|
149
|
+
* @param {Number} seconds
|
|
150
|
+
* @param {String} op - like sub, add, mul, sub
|
|
151
151
|
*
|
|
152
152
|
* @returns {Object} Date
|
|
153
153
|
*/
|
|
154
|
-
changeTime(date,
|
|
154
|
+
changeTime(date, seconds, op) {
|
|
155
155
|
if (date === undefined) return null;
|
|
156
156
|
|
|
157
157
|
if (op === 'sub') {
|
|
158
|
-
return new Date(date.getTime() -
|
|
158
|
+
return new Date(date.getTime() - seconds * 1000);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
return new Date(date.getTime() +
|
|
161
|
+
return new Date(date.getTime() + seconds * 1000);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
@@ -17,7 +17,7 @@ export class LoanTokenPoller {
|
|
|
17
17
|
this.pollerDelay = pollerDelay; // value in seconds
|
|
18
18
|
|
|
19
19
|
this.loanTokenInterval = undefined;
|
|
20
|
-
this.
|
|
20
|
+
this.bookAccessed();
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
disconnectedInterval() {
|
|
@@ -33,7 +33,7 @@ export class LoanTokenPoller {
|
|
|
33
33
|
// }
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
async
|
|
36
|
+
async bookAccessed() {
|
|
37
37
|
let consecutiveLoanCounts = 1;
|
|
38
38
|
|
|
39
39
|
if (this.borrowType) {
|
|
@@ -73,7 +73,7 @@ export class LoanTokenPoller {
|
|
|
73
73
|
this.sendEvent(category, action);
|
|
74
74
|
} else {
|
|
75
75
|
window?.Sentry?.captureMessage(
|
|
76
|
-
`${sentryLogs.
|
|
76
|
+
`${sentryLogs.bookAccessed} - not borrowed`
|
|
77
77
|
);
|
|
78
78
|
|
|
79
79
|
// if book is not browsed, just clear token polling interval
|
package/src/ia-book-actions.js
CHANGED
|
@@ -42,7 +42,7 @@ export default class IABookActions extends LitElement {
|
|
|
42
42
|
modal: { Object },
|
|
43
43
|
tokenDelay: { type: Number },
|
|
44
44
|
localCache: { type: Object },
|
|
45
|
-
|
|
45
|
+
loanRenewTimeConfig: { type: Object },
|
|
46
46
|
loanRenewResult: { type: Object },
|
|
47
47
|
};
|
|
48
48
|
}
|
|
@@ -71,30 +71,34 @@ export default class IABookActions extends LitElement {
|
|
|
71
71
|
this.lendingOptions = {};
|
|
72
72
|
this.borrowType = ''; // (browsed|borrowed)
|
|
73
73
|
this.consecutiveLoanCounts = 1; // consecutive loan count
|
|
74
|
+
this.suppressToast = false;
|
|
75
|
+
this.browseTimer = undefined;
|
|
74
76
|
|
|
75
77
|
/**
|
|
76
|
-
* contains loan
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* -
|
|
80
|
-
*
|
|
78
|
+
* contains one hour auto-loan-renew time configuration
|
|
79
|
+
*
|
|
80
|
+
* @type {object} loanRenewTimeConfig
|
|
81
|
+
* @property {number} loanTotalTime - number of seconds a loan should last
|
|
82
|
+
* @property {number} loanRenewAtLast - check for loan renew at last
|
|
83
|
+
* @property {number} pageChangedInLast - consider loan renew eligible if viewed new page
|
|
84
|
+
* @property {boolean} isDevBox - testing flag
|
|
81
85
|
*/
|
|
82
|
-
this.
|
|
83
|
-
this.suppressToast = false;
|
|
84
|
-
this.browseTimer = undefined;
|
|
86
|
+
this.loanRenewTimeConfig = {};
|
|
85
87
|
|
|
86
88
|
/**
|
|
87
|
-
* contains
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* -
|
|
89
|
+
* contains one hour auto-loan-renew response
|
|
90
|
+
*
|
|
91
|
+
* @type {object} loanRenewResult
|
|
92
|
+
* @property {string} texts - texts messages need to show in toast message
|
|
93
|
+
* @property {boolean} renewNow - key to determine if need to renew now
|
|
94
|
+
* @property {number} secondsLeft - seconds left in active loan
|
|
91
95
|
*/
|
|
92
|
-
this.loanRenewResult = {
|
|
93
|
-
texts: null,
|
|
94
|
-
renewNow: false,
|
|
95
|
-
timeLeft: 0,
|
|
96
|
-
};
|
|
96
|
+
this.loanRenewResult = { texts: '', renewNow: false, secondsLeft: 0 };
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* need showdowRoot opened for resetTimerCountState
|
|
100
|
+
* @see IABookActions::resetTimerCountState
|
|
101
|
+
*/
|
|
98
102
|
this._shadowRoot = this.attachShadow({ mode: 'open' });
|
|
99
103
|
}
|
|
100
104
|
|
|
@@ -210,7 +214,6 @@ export default class IABookActions extends LitElement {
|
|
|
210
214
|
|
|
211
215
|
if (this.borrowType === 'browsed') {
|
|
212
216
|
// start timer for browsed.
|
|
213
|
-
// when browse is completed, we shows browse-again button
|
|
214
217
|
this.startBrowseTimer();
|
|
215
218
|
}
|
|
216
219
|
|
|
@@ -236,6 +239,8 @@ export default class IABookActions extends LitElement {
|
|
|
236
239
|
() => {
|
|
237
240
|
this.startLoanTokenPoller();
|
|
238
241
|
},
|
|
242
|
+
|
|
243
|
+
// if book is renew while reading, let's wait to execute create-token api
|
|
239
244
|
this.loanRenewResult.renewNow ? this.tokenDelay * 1000 : 100
|
|
240
245
|
);
|
|
241
246
|
}
|
|
@@ -243,8 +248,9 @@ export default class IABookActions extends LitElement {
|
|
|
243
248
|
/**
|
|
244
249
|
* Bind 1 hour loan auto renew event,
|
|
245
250
|
* There are two events we want to use,
|
|
246
|
-
* 1. BookReader:
|
|
247
|
-
* 2.
|
|
251
|
+
* 1. BookReader:userAction - dispatched from bookreader side
|
|
252
|
+
* 2. click event to refresh the page when book is auto expired
|
|
253
|
+
* 3. IABookActions:loanRenew - dispatched from timer-countdown component
|
|
248
254
|
*/
|
|
249
255
|
bindLoanRenewEvents() {
|
|
250
256
|
/**
|
|
@@ -260,10 +266,10 @@ export default class IABookActions extends LitElement {
|
|
|
260
266
|
});
|
|
261
267
|
|
|
262
268
|
/**
|
|
263
|
-
*
|
|
269
|
+
* detect click-event on document to close toast-template
|
|
264
270
|
*/
|
|
265
271
|
document.addEventListener('click', e => {
|
|
266
|
-
if (this.loanRenewHelper && this.loanRenewResult.
|
|
272
|
+
if (this.loanRenewHelper && this.loanRenewResult.secondsLeft > 0) {
|
|
267
273
|
console.log('clicked-outside');
|
|
268
274
|
this.suppressToast = true;
|
|
269
275
|
}
|
|
@@ -281,13 +287,14 @@ export default class IABookActions extends LitElement {
|
|
|
281
287
|
* this event dispatched from timer-countdown component for:
|
|
282
288
|
* 1. user turned book page after showing auto-returned warning message
|
|
283
289
|
* 2. show warning message having remaining time
|
|
290
|
+
* @see TimerCountdown::timerCountdown
|
|
284
291
|
*/
|
|
285
292
|
this.addEventListener('IABookActions:loanRenew', async event => {
|
|
286
293
|
await this.autoLoanRenewChecker(false);
|
|
287
294
|
|
|
288
295
|
// show warning message with remaining time to auto returned it.
|
|
289
296
|
if (this.loanRenewResult.renewNow === false) {
|
|
290
|
-
this.loanRenewResult.
|
|
297
|
+
this.loanRenewResult.secondsLeft = event.detail.secondsLeft;
|
|
291
298
|
this.showToastMessage();
|
|
292
299
|
}
|
|
293
300
|
});
|
|
@@ -295,6 +302,7 @@ export default class IABookActions extends LitElement {
|
|
|
295
302
|
|
|
296
303
|
/**
|
|
297
304
|
* To determine if need to be renewed browsed book
|
|
305
|
+
* @see LoanRenewHelper
|
|
298
306
|
*
|
|
299
307
|
* @param {Boolean} hasPageChanged
|
|
300
308
|
*/
|
|
@@ -303,7 +311,7 @@ export default class IABookActions extends LitElement {
|
|
|
303
311
|
hasPageChanged,
|
|
304
312
|
this.identifier,
|
|
305
313
|
this.localCache,
|
|
306
|
-
this.
|
|
314
|
+
this.loanRenewTimeConfig
|
|
307
315
|
);
|
|
308
316
|
|
|
309
317
|
await this.loanRenewHelper.handleLoanRenew();
|
|
@@ -312,9 +320,9 @@ export default class IABookActions extends LitElement {
|
|
|
312
320
|
|
|
313
321
|
/**
|
|
314
322
|
* Show toast messages on some specific loan renew features. e.g.
|
|
315
|
-
* - show
|
|
316
|
-
* - show
|
|
317
|
-
* - show
|
|
323
|
+
* - show message when book is auto renewed
|
|
324
|
+
* - show message when book is expired
|
|
325
|
+
* - show message having remaining time when book is about to auto returned
|
|
318
326
|
*/
|
|
319
327
|
async showToastMessage() {
|
|
320
328
|
if (this.suppressToast) return;
|
|
@@ -329,11 +337,12 @@ export default class IABookActions extends LitElement {
|
|
|
329
337
|
await iaBookActions.appendChild(toastTemplate);
|
|
330
338
|
|
|
331
339
|
const config = new ToastConfig();
|
|
340
|
+
config.dismisOnClick = true;
|
|
332
341
|
config.texts = this.loanRenewHelper?.getMessageTexts(
|
|
333
342
|
this.loanRenewResult.texts,
|
|
334
|
-
this.loanRenewResult.
|
|
343
|
+
this.loanRenewResult.secondsLeft
|
|
335
344
|
);
|
|
336
|
-
|
|
345
|
+
|
|
337
346
|
toastTemplate.showToast({
|
|
338
347
|
config,
|
|
339
348
|
});
|
|
@@ -404,14 +413,14 @@ export default class IABookActions extends LitElement {
|
|
|
404
413
|
|
|
405
414
|
const secondsLeft = Number(this.lendingStatus.secondsLeftOnLoan);
|
|
406
415
|
const strokeDashOffset =
|
|
407
|
-
(secondsLeft / this.
|
|
416
|
+
(secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315;
|
|
408
417
|
|
|
409
418
|
// set seconds left in loan expire
|
|
410
|
-
timerCountdown.style?.setProperty('--
|
|
419
|
+
timerCountdown.style?.setProperty('--secondsLeftOnLoan', `${secondsLeft}s`);
|
|
411
420
|
|
|
412
421
|
// set circle stroke offset left in loan expire
|
|
413
422
|
timerCountdown.style?.setProperty(
|
|
414
|
-
'--
|
|
423
|
+
'--strokeLeftOnLoan',
|
|
415
424
|
`${Number(strokeDashOffset)}` // the perimeter of the circle = (π * 2 * radius)
|
|
416
425
|
);
|
|
417
426
|
|
|
@@ -444,8 +453,9 @@ export default class IABookActions extends LitElement {
|
|
|
444
453
|
get timerCountdownTemplate() {
|
|
445
454
|
return this.borrowType === 'browsed'
|
|
446
455
|
? html`<timer-countdown
|
|
447
|
-
.
|
|
448
|
-
.
|
|
456
|
+
.secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
|
|
457
|
+
.loanRenewAtLast=${this.loanRenewTimeConfig.loanRenewAtLast}
|
|
458
|
+
.isDevBox=${this.loanRenewTimeConfig.isDevBox}
|
|
449
459
|
></timer-countdown>`
|
|
450
460
|
: nothing;
|
|
451
461
|
}
|
|
@@ -462,7 +472,7 @@ export default class IABookActions extends LitElement {
|
|
|
462
472
|
.borrowType=${this.borrowType}
|
|
463
473
|
.returnUrl=${this.returnUrl}
|
|
464
474
|
.localCache=${this.localCache}
|
|
465
|
-
.
|
|
475
|
+
.loanTotalTime=${this.loanRenewTimeConfig.loanTotalTime}
|
|
466
476
|
?hasAdminAccess=${this.hasAdminAccess}
|
|
467
477
|
?disabled=${this.disableActionGroup}
|
|
468
478
|
?renewNow=${this.loanRenewResult.renewNow}
|
|
@@ -492,7 +502,9 @@ export default class IABookActions extends LitElement {
|
|
|
492
502
|
await this.resetTimerCountState();
|
|
493
503
|
|
|
494
504
|
window?.Sentry?.captureMessage(`${sentryLogs.bookHasRenewed}`);
|
|
505
|
+
// analytics?? for consecutive renew.....
|
|
495
506
|
|
|
507
|
+
// testing console....
|
|
496
508
|
console.log(sentryLogs.bookHasRenewed, {
|
|
497
509
|
loanRenewResult: this.loanRenewResult,
|
|
498
510
|
browseHasRenew: this.lendingStatus.secondsLeftOnLoan,
|
|
@@ -503,6 +515,7 @@ export default class IABookActions extends LitElement {
|
|
|
503
515
|
|
|
504
516
|
/**
|
|
505
517
|
* enable access of borrowed/browsed books
|
|
518
|
+
* @see LoanTokenPoller
|
|
506
519
|
*/
|
|
507
520
|
startLoanTokenPoller() {
|
|
508
521
|
if (this.tokenPoller) {
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { html, fixture, expect, aTimeout } from '@open-wc/testing';
|
|
2
2
|
import '../../src/components/timer-countdown.js';
|
|
3
3
|
|
|
4
|
-
const container = ({
|
|
4
|
+
const container = ({ secondsLeftOnLoan, loanRenewTimeConfig } = {}) =>
|
|
5
5
|
html`<timer-countdown
|
|
6
|
-
.
|
|
7
|
-
.
|
|
6
|
+
.secondsLeftOnLoan=${secondsLeftOnLoan}
|
|
7
|
+
.loanRenewTimeConfig=${loanRenewTimeConfig}
|
|
8
8
|
></timer-countdown>`;
|
|
9
9
|
|
|
10
10
|
describe('<timer-countdown>', () => {
|
|
11
11
|
it('timer interval is undefined when loan is expired', async () => {
|
|
12
12
|
const el = await fixture(
|
|
13
13
|
container({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
secondsLeftOnLoan: 0, // in seconds
|
|
15
|
+
loanRenewTimeConfig: {
|
|
16
|
+
loanTotalTime: 14, // in seconds
|
|
17
|
+
loanRenewAtLast: 5, // in seconds
|
|
18
18
|
pageChangedInLast: 5, // in seconds
|
|
19
19
|
isDevBox: true,
|
|
20
20
|
},
|
|
@@ -28,10 +28,10 @@ describe('<timer-countdown>', () => {
|
|
|
28
28
|
it('timer interval is not undefined when loan is active', async () => {
|
|
29
29
|
const el = await fixture(
|
|
30
30
|
container({
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
secondsLeftOnLoan: 2, // in seconds
|
|
32
|
+
loanRenewTimeConfig: {
|
|
33
|
+
loanTotalTime: 14, // in seconds
|
|
34
|
+
loanRenewAtLast: 5, // in seconds
|
|
35
35
|
pageChangedInLast: 5, // in seconds
|
|
36
36
|
isDevBox: true,
|
|
37
37
|
},
|
|
@@ -41,7 +41,7 @@ describe('<timer-countdown>', () => {
|
|
|
41
41
|
await aTimeout(1900);
|
|
42
42
|
await el.updateComplete;
|
|
43
43
|
|
|
44
|
-
expect(el.
|
|
44
|
+
expect(el.secondsLeftOnLoan).to.equal(2);
|
|
45
45
|
expect(el.timerInterval).to.not.be.undefined;
|
|
46
46
|
});
|
|
47
47
|
});
|
|
@@ -4,9 +4,9 @@ import { LocalCache } from '@internetarchive/local-cache';
|
|
|
4
4
|
import { LoanRenewHelper } from '../../../src/core/services/loan-renew-helper.js';
|
|
5
5
|
|
|
6
6
|
const identifier = 'booBar';
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const loanRenewTimeConfig = {
|
|
8
|
+
loanTotalTime: 13,
|
|
9
|
+
loanRenewAtLast: 10,
|
|
10
10
|
pageChangedInLast: 12,
|
|
11
11
|
isDevBox: true,
|
|
12
12
|
};
|
|
@@ -19,8 +19,10 @@ const localCache = new LocalCache({
|
|
|
19
19
|
beforeEach(async () => {
|
|
20
20
|
await localCache.set({
|
|
21
21
|
key: `${identifier}-loanTime`,
|
|
22
|
-
value: new Date(
|
|
23
|
-
|
|
22
|
+
value: new Date(
|
|
23
|
+
new Date().getTime() + loanRenewTimeConfig.loanTotalTime * 1000
|
|
24
|
+
),
|
|
25
|
+
ttl: Number(loanRenewTimeConfig.loanTotalTime),
|
|
24
26
|
});
|
|
25
27
|
});
|
|
26
28
|
|
|
@@ -31,14 +33,14 @@ describe('Loan Renew Determine', () => {
|
|
|
31
33
|
await localCache.set({
|
|
32
34
|
key: `${identifier}-pageChangedTime`,
|
|
33
35
|
value: new Date(), // current time
|
|
34
|
-
ttl: Number(
|
|
36
|
+
ttl: Number(loanRenewTimeConfig.loanTotalTime),
|
|
35
37
|
});
|
|
36
38
|
|
|
37
39
|
const loanRenewHelper = new LoanRenewHelper(
|
|
38
40
|
true, // hasPageChanged
|
|
39
41
|
identifier,
|
|
40
42
|
localCache,
|
|
41
|
-
|
|
43
|
+
loanRenewTimeConfig
|
|
42
44
|
);
|
|
43
45
|
await loanRenewHelper.handleLoanRenew();
|
|
44
46
|
|
|
@@ -49,7 +51,7 @@ describe('Loan Renew Determine', () => {
|
|
|
49
51
|
await localCache.set({
|
|
50
52
|
key: `${identifier}-pageChangedTime`,
|
|
51
53
|
value: new Date(), // current time
|
|
52
|
-
ttl: Number(
|
|
54
|
+
ttl: Number(loanRenewTimeConfig.loanTotalTime),
|
|
53
55
|
});
|
|
54
56
|
|
|
55
57
|
await aTimeout(1500);
|
|
@@ -58,7 +60,7 @@ describe('Loan Renew Determine', () => {
|
|
|
58
60
|
false, // timer-countdown event
|
|
59
61
|
identifier,
|
|
60
62
|
localCache,
|
|
61
|
-
|
|
63
|
+
loanRenewTimeConfig
|
|
62
64
|
);
|
|
63
65
|
await loanRenewHelper.handleLoanRenew();
|
|
64
66
|
|
|
@@ -70,12 +72,12 @@ describe('Loan Renew Determine', () => {
|
|
|
70
72
|
false,
|
|
71
73
|
identifier,
|
|
72
74
|
localCache,
|
|
73
|
-
|
|
75
|
+
loanRenewTimeConfig
|
|
74
76
|
);
|
|
75
77
|
|
|
76
78
|
const toastMsg = loanRenewHelper.getMessageTexts(
|
|
77
79
|
loanRenewHelper.loanReturnWarning,
|
|
78
|
-
'65'
|
|
80
|
+
'65' // in seconds
|
|
79
81
|
);
|
|
80
82
|
|
|
81
83
|
expect(toastMsg).to.be.equal(
|
|
@@ -241,9 +241,9 @@ describe('Browsing expired status', () => {
|
|
|
241
241
|
expect(el.primaryActions[1].text).to.equal('Print Disability Access');
|
|
242
242
|
|
|
243
243
|
// default params of one-hour loan renew
|
|
244
|
-
expect(el.loanRenewResult.texts).to.equal(
|
|
244
|
+
expect(el.loanRenewResult.texts).to.equal('');
|
|
245
245
|
expect(el.loanRenewResult.renewNow).to.equal(false);
|
|
246
|
-
expect(el.loanRenewResult.
|
|
246
|
+
expect(el.loanRenewResult.secondsLeft).to.equal(0);
|
|
247
247
|
});
|
|
248
248
|
|
|
249
249
|
it('Book is browsing and going to expire after 1 second', async () => {
|
|
@@ -272,7 +272,7 @@ describe('Browsing expired status', () => {
|
|
|
272
272
|
|
|
273
273
|
// // book has been expired
|
|
274
274
|
expect(el.loanRenewResult.renewNow).to.equal(false);
|
|
275
|
-
expect(el.loanRenewResult.
|
|
275
|
+
expect(el.loanRenewResult.secondsLeft).to.equal(0);
|
|
276
276
|
expect(el.loanRenewResult.texts).to.equal(
|
|
277
277
|
'This book has been automatically returned due to inactivity.'
|
|
278
278
|
);
|
|
@@ -332,7 +332,7 @@ describe('Auto renew one hour loan', () => {
|
|
|
332
332
|
el.loanRenewResult = {
|
|
333
333
|
texts: 'This book has been renewed for 1 hour.',
|
|
334
334
|
renewNow: true,
|
|
335
|
-
|
|
335
|
+
secondsLeft: 10,
|
|
336
336
|
};
|
|
337
337
|
|
|
338
338
|
await localCache.set({
|
|
@@ -350,11 +350,11 @@ describe('Auto renew one hour loan', () => {
|
|
|
350
350
|
await aTimeout(1500); // wait for 1.5 second
|
|
351
351
|
await el.updateComplete;
|
|
352
352
|
|
|
353
|
-
expect(el.loanRenewResult.timeLeft).to.equal(10);
|
|
354
|
-
expect(el.loanRenewResult.renewNow).to.equal(true);
|
|
355
353
|
expect(el.loanRenewResult.texts).to.equal(
|
|
356
354
|
'This book has been renewed for 1 hour.'
|
|
357
355
|
);
|
|
356
|
+
expect(el.loanRenewResult.renewNow).to.equal(true);
|
|
357
|
+
expect(el.loanRenewResult.secondsLeft).to.equal(10);
|
|
358
358
|
});
|
|
359
359
|
});
|
|
360
360
|
|