@internetarchive/ia-book-actions 1.1.0-alpha14 → 1.1.0-alpha15
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
CHANGED
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
--primaryCTAFillRGB: 25, 72, 128;
|
|
35
35
|
--primaryErrorCTAFillRGB: 229, 28, 38;
|
|
36
36
|
--primaryDisableCTAFill: #767676;
|
|
37
|
+
background: var(--secondaryBGColor);
|
|
38
|
+
color: var(--primaryTextColor);
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
fieldset {
|
|
@@ -76,6 +78,13 @@
|
|
|
76
78
|
display: inline-grid;
|
|
77
79
|
}
|
|
78
80
|
|
|
81
|
+
.action-button button {
|
|
82
|
+
padding: 6px;
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
border: 2px solid #194880;
|
|
85
|
+
border-radius: 10px;
|
|
86
|
+
}
|
|
87
|
+
|
|
79
88
|
body.modal-manager-open {
|
|
80
89
|
overflow: hidden;
|
|
81
90
|
}
|
|
@@ -128,10 +137,11 @@
|
|
|
128
137
|
iaBookActions.modalConfig = modalConfig;
|
|
129
138
|
iaBookActions.lendingBarPostInit = lendingBarPostInit;
|
|
130
139
|
iaBookActions.tokenDelay = 2; // 2 seconds
|
|
140
|
+
iaBookActions.timerExecutionSeconds = 4 // 4 seconds
|
|
131
141
|
iaBookActions.returnUrl = '';
|
|
132
142
|
iaBookActions.localCache = localCache;
|
|
133
143
|
|
|
134
|
-
let loanTotalTime2Min = { loanTotalTime:
|
|
144
|
+
let loanTotalTime2Min = { loanTotalTime: 120, loanRenewAtLast: 80, pageChangedInLast: 15 };
|
|
135
145
|
let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 180, pageChangedInLast: 15 };
|
|
136
146
|
let loanTotalTime1Hour = { loanTotalTime: 3600, loanRenewAtLast: 660, pageChangedInLast: 900 };
|
|
137
147
|
|
|
@@ -286,6 +296,19 @@
|
|
|
286
296
|
iaBookActions.browseHasExpired();
|
|
287
297
|
});
|
|
288
298
|
|
|
299
|
+
document.querySelector('#resync_timer').addEventListener('click', async (e) => {
|
|
300
|
+
if (iaBookActions.lendingStatus.user_has_browsed) {
|
|
301
|
+
document.querySelector('ia-book-actions').dispatchEvent(
|
|
302
|
+
new Event('visibilitychange', {
|
|
303
|
+
detail: {},
|
|
304
|
+
bubbles: true,
|
|
305
|
+
composed: true,
|
|
306
|
+
})
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
310
|
+
});
|
|
311
|
+
|
|
289
312
|
document.querySelectorAll('.availableToBorrow input[type=radio]').forEach((item) => {
|
|
290
313
|
item.addEventListener('click', (e) => {
|
|
291
314
|
if (e.target.value === 'available_to_borrow') {
|
|
@@ -359,9 +382,6 @@
|
|
|
359
382
|
</td>
|
|
360
383
|
<td class="searchParam">
|
|
361
384
|
<label><input type="checkbox" name="search" value="Search Param" />Search Param</label>
|
|
362
|
-
<td>
|
|
363
|
-
<button class="pageChangedEvent">Page Change Event</button>
|
|
364
|
-
</td>
|
|
365
385
|
</tr>
|
|
366
386
|
</table>
|
|
367
387
|
</fieldset>
|
|
@@ -385,12 +405,6 @@
|
|
|
385
405
|
<label><input type="radio" name="browse" value="available_to_browse" />available_to_browse</label>
|
|
386
406
|
<label><input type="radio" name="browse" value="user_has_browsed" />user_has_browsed</label>
|
|
387
407
|
<label><input type="radio" name="browse" value="browsingExpired" />browsingExpired</label>
|
|
388
|
-
<div>
|
|
389
|
-
<button id="show_warning_modal">When Browsing (`user_has_browsed`), show Warning Modal</button>
|
|
390
|
-
</div>
|
|
391
|
-
<div>
|
|
392
|
-
<button id="show_expired_modal">While Browsing (`user_has_browsed`), Expire book & show its modal</button>
|
|
393
|
-
</div>
|
|
394
408
|
</td>
|
|
395
409
|
<td class="availableToBorrow">
|
|
396
410
|
<label><input type="radio" name="borrow" value="available_to_borrow" />available_to_borrow</label>
|
|
@@ -410,6 +424,29 @@
|
|
|
410
424
|
font-weight: bold; display: none" name="purchase" value="Reflect" />
|
|
411
425
|
</td>
|
|
412
426
|
</tr>
|
|
427
|
+
<tr>
|
|
428
|
+
<td>
|
|
429
|
+
<fieldset style="margin-top: 10px;">
|
|
430
|
+
<legend style="color: black;">controls for browsed book</legend>
|
|
431
|
+
<table aria-hidden="true">
|
|
432
|
+
<tbody><tr>
|
|
433
|
+
<td class="action-button">
|
|
434
|
+
<button class="pageChangedEvent">Page Change Event</button>
|
|
435
|
+
</td>
|
|
436
|
+
<td class="action-button">
|
|
437
|
+
<button id="show_warning_modal">When Browsing (`user_has_browsed`),<br> show Warning Modal</button>
|
|
438
|
+
</td>
|
|
439
|
+
<td class="action-button">
|
|
440
|
+
<button id="show_expired_modal">While Browsing (`user_has_browsed`),<br> Expire book & show its modal</button>
|
|
441
|
+
</td>
|
|
442
|
+
<td class="action-button">
|
|
443
|
+
<button id="resync_timer">While Browsing (`user_has_browsed`),<br> resync timer</button>
|
|
444
|
+
</td>
|
|
445
|
+
</tr>
|
|
446
|
+
</tbody></table>
|
|
447
|
+
</fieldset>
|
|
448
|
+
</td>
|
|
449
|
+
</tr>
|
|
413
450
|
</table>
|
|
414
451
|
</fieldset>
|
|
415
452
|
</div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "1.1.0-
|
|
3
|
+
"version": "1.1.0-alpha15",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"lint": "eslint --ext .js,.html . --ignore-path .gitignore && prettier \"**/*.js\" --check --ignore-path .gitignore",
|
|
15
15
|
"format": "eslint --ext .js,.html . --fix --ignore-path .gitignore && prettier \"**/*.js\" --write --ignore-path .gitignore",
|
|
16
16
|
"test": "yarn run lint && yarn test:fast",
|
|
17
|
-
"test:fast": "web-test-runner --coverage",
|
|
18
|
-
"test:watch": "web-test-runner --watch"
|
|
17
|
+
"test:fast": "web-test-runner --coverage --playwright --browsers chromium firefox webkit",
|
|
18
|
+
"test:watch": "web-test-runner --watch --playwright --browsers chromium firefox webkit"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@internetarchive/icon-info": "^1.2.6",
|
|
@@ -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,
|
package/src/ia-book-actions.js
CHANGED
|
@@ -59,6 +59,7 @@ export default class IABookActions extends LitElement {
|
|
|
59
59
|
disableActionGroup: { type: Boolean },
|
|
60
60
|
modal: { Object },
|
|
61
61
|
tokenDelay: { type: Number },
|
|
62
|
+
timerExecutionSeconds: { type: Number },
|
|
62
63
|
localCache: { type: Object },
|
|
63
64
|
loanRenewTimeConfig: { type: Object },
|
|
64
65
|
loanRenewResult: { type: Object },
|
|
@@ -79,6 +80,7 @@ export default class IABookActions extends LitElement {
|
|
|
79
80
|
this.sharedObserver = undefined;
|
|
80
81
|
this.disableActionGroup = false;
|
|
81
82
|
this.tokenDelay = 120; // in seconds
|
|
83
|
+
this.timerExecutionSeconds = 30;
|
|
82
84
|
|
|
83
85
|
// private props
|
|
84
86
|
this.postInitComplete = false;
|
|
@@ -89,10 +91,6 @@ export default class IABookActions extends LitElement {
|
|
|
89
91
|
this.lendingOptions = {};
|
|
90
92
|
this.borrowType = null; // 'browsed'|'borrowed'
|
|
91
93
|
this.browseTimer = undefined; // timeout
|
|
92
|
-
this.timerExecutionSeconds = 10;
|
|
93
|
-
|
|
94
|
-
/** @deprecated */
|
|
95
|
-
this.toast = undefined;
|
|
96
94
|
|
|
97
95
|
/**
|
|
98
96
|
* when user click on [return the book] button on warning modal
|
|
@@ -117,7 +115,7 @@ export default class IABookActions extends LitElement {
|
|
|
117
115
|
* contains one hour auto-loan-renew response
|
|
118
116
|
*
|
|
119
117
|
* @type {object} loanRenewResult
|
|
120
|
-
* @property {string} texts - texts messages
|
|
118
|
+
* @property {string} texts - texts messages shows in modal
|
|
121
119
|
* @property {boolean} renewNow - key to determine if need to renew now
|
|
122
120
|
* @property {number} secondsLeft - seconds left in active loan
|
|
123
121
|
*/
|
|
@@ -132,10 +130,13 @@ export default class IABookActions extends LitElement {
|
|
|
132
130
|
this.disconnectResizeObserver();
|
|
133
131
|
}
|
|
134
132
|
|
|
133
|
+
/**
|
|
134
|
+
* send log messages to sentry
|
|
135
|
+
* @param {string} msg
|
|
136
|
+
*/
|
|
135
137
|
sentryCaptureMsg(msg) {
|
|
136
138
|
log(window?.Sentry);
|
|
137
|
-
|
|
138
|
-
if (window?.Sentry) window?.Sentry?.captureMessage(msg);
|
|
139
|
+
window?.Sentry?.captureMessage(msg);
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
firstUpdated() {
|
|
@@ -291,19 +292,31 @@ export default class IABookActions extends LitElement {
|
|
|
291
292
|
|
|
292
293
|
/**
|
|
293
294
|
* auto-renew interval may stale when tab is in background,
|
|
294
|
-
* when user
|
|
295
|
+
* so when user open that tab again,
|
|
295
296
|
* the [visibilitychange] event can trigger timer to show relavent messages
|
|
296
297
|
*/
|
|
297
|
-
document.addEventListener(
|
|
298
|
+
document.addEventListener('visibilitychange', async () => {
|
|
298
299
|
if (!document.hidden) {
|
|
299
|
-
log(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
300
|
+
log(
|
|
301
|
+
'visibilitychange event execute:------------------ ',
|
|
302
|
+
new Date().getMinutes(),
|
|
303
|
+
new Date().getSeconds(),
|
|
304
|
+
this.borrowType
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
if (
|
|
308
|
+
this.borrowType === 'browsed' &&
|
|
309
|
+
this.lendingStatus.browsingExpired === false
|
|
310
|
+
) {
|
|
311
|
+
const loanTime = await this.localCache.get(
|
|
312
|
+
`${this.identifier}-loanTime`
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// number of seconds left in current loan
|
|
316
|
+
const secondsLeft = Math.round((loanTime - new Date()) / 1000);
|
|
304
317
|
|
|
305
318
|
if (secondsLeft >= this.timerExecutionSeconds) {
|
|
306
|
-
this.
|
|
319
|
+
this.loanStatusCheckInterval(Number(secondsLeft));
|
|
307
320
|
} else {
|
|
308
321
|
this.browseHasExpired();
|
|
309
322
|
this.disconnectedCallback();
|
|
@@ -490,31 +503,6 @@ export default class IABookActions extends LitElement {
|
|
|
490
503
|
await this.modal?.showModal({ config, customModalContent });
|
|
491
504
|
}
|
|
492
505
|
|
|
493
|
-
/**
|
|
494
|
-
* @deprecated
|
|
495
|
-
* create / select the toast-template component on DOM
|
|
496
|
-
*
|
|
497
|
-
* @memberof IABookActions
|
|
498
|
-
*/
|
|
499
|
-
async useToastManager() {
|
|
500
|
-
if (!this.toast) {
|
|
501
|
-
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
502
|
-
|
|
503
|
-
if (!this.toast) this.toast = document.createElement('toast-template');
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
await this.shadowRoot.appendChild(this.toast);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* @deprecated
|
|
511
|
-
* close/hide toast message
|
|
512
|
-
*/
|
|
513
|
-
async closeToastManager() {
|
|
514
|
-
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
515
|
-
this.toast?.remove();
|
|
516
|
-
}
|
|
517
|
-
|
|
518
506
|
/**
|
|
519
507
|
* Execute when loan is expired
|
|
520
508
|
*/
|
|
@@ -643,7 +631,10 @@ export default class IABookActions extends LitElement {
|
|
|
643
631
|
if (this.loanRenewResult.renewNow) {
|
|
644
632
|
// Now, let's reset loan duration & this.lendingStatus
|
|
645
633
|
const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
|
|
646
|
-
|
|
634
|
+
|
|
635
|
+
// number of seconds left in current loan
|
|
636
|
+
const secondsLeft = Math.round((loanTime - new Date()) / 1000);
|
|
637
|
+
log(loanTime, secondsLeft);
|
|
647
638
|
|
|
648
639
|
log('IABookActions: handleLoanAutoRenewed --- ', {
|
|
649
640
|
ajaxResponse: detail?.data,
|
|
@@ -680,7 +671,7 @@ export default class IABookActions extends LitElement {
|
|
|
680
671
|
|
|
681
672
|
window.IALendingIntervals.timerCountdown = setInterval(async () => {
|
|
682
673
|
// interval execution block
|
|
683
|
-
await this.
|
|
674
|
+
await this.loanStatusCheckInterval(secondsLeft);
|
|
684
675
|
}, this.timerExecutionSeconds * 1000);
|
|
685
676
|
}
|
|
686
677
|
|
|
@@ -689,10 +680,10 @@ export default class IABookActions extends LitElement {
|
|
|
689
680
|
* - if setInterval timer gone off, let's resync
|
|
690
681
|
* - loan-renew attempt to renew the loan OR show relavant message
|
|
691
682
|
* - if loan has expired, clear interval timers
|
|
692
|
-
*
|
|
693
|
-
* @param {Number} secondsLeftOnLoan
|
|
683
|
+
*
|
|
684
|
+
* @param {Number} secondsLeftOnLoan
|
|
694
685
|
*/
|
|
695
|
-
async
|
|
686
|
+
async loanStatusCheckInterval(secondsLeftOnLoan) {
|
|
696
687
|
let secondsLeft = secondsLeftOnLoan;
|
|
697
688
|
secondsLeft -= this.timerExecutionSeconds;
|
|
698
689
|
secondsLeft = Math.round(secondsLeft); // round number
|
|
@@ -702,21 +693,30 @@ export default class IABookActions extends LitElement {
|
|
|
702
693
|
// if really updated, escape from here
|
|
703
694
|
const resyncd = await this.reSyncTimerIfGoneOff(secondsLeft);
|
|
704
695
|
|
|
705
|
-
if (resyncd
|
|
696
|
+
if (resyncd.hasSynced) {
|
|
706
697
|
secondsLeft = resyncd.whatShouldLeft;
|
|
707
698
|
log('startTimerCountdown --- stale, timer has resyncd', {
|
|
708
699
|
secondsLeft,
|
|
709
700
|
});
|
|
710
701
|
}
|
|
711
702
|
|
|
712
|
-
log(
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
703
|
+
log(
|
|
704
|
+
'startTimerCountdown --- countdown still valid. continue...',
|
|
705
|
+
{
|
|
706
|
+
resyncd,
|
|
707
|
+
secondsLeft,
|
|
708
|
+
loanRenewAtLast: this.loanRenewTimeConfig.loanRenewAtLast,
|
|
709
|
+
},
|
|
710
|
+
'time: ',
|
|
711
|
+
new Date().getMinutes(),
|
|
712
|
+
':',
|
|
713
|
+
new Date().getSeconds(),
|
|
714
|
+
', timerDelay: ',
|
|
715
|
+
this.timerExecutionSeconds
|
|
716
|
+
);
|
|
717
717
|
|
|
718
718
|
/**
|
|
719
|
-
* execute from last 10th
|
|
719
|
+
* execute from last 10th minutes to 0th minute
|
|
720
720
|
* - 10th - to check if user has viewed
|
|
721
721
|
* - till 0th - to show warning msg with remaining time to auto expired
|
|
722
722
|
* @see IABookActions::bindLoanRenewEvents
|
|
@@ -736,8 +736,7 @@ export default class IABookActions extends LitElement {
|
|
|
736
736
|
* helper function to determine if timer is not in sync properly
|
|
737
737
|
*
|
|
738
738
|
* @param {number} timerSecondsLeft - actual seconds left get from setInterval
|
|
739
|
-
*
|
|
740
|
-
* @memberof TimerCountdown
|
|
739
|
+
* @returns {Object} { hasSynced: [boolean], whatShouldLeft: [number] }
|
|
741
740
|
*/
|
|
742
741
|
async reSyncTimerIfGoneOff(timerSecondsLeft) {
|
|
743
742
|
const currentTime = new Date();
|
|
@@ -772,10 +771,10 @@ export default class IABookActions extends LitElement {
|
|
|
772
771
|
|
|
773
772
|
if (whatIsleft !== whatShouldLeft) {
|
|
774
773
|
log(`reSyncTimerIfGoneOff --- let's re-sync.`);
|
|
775
|
-
|
|
776
774
|
return { hasSynced: true, whatShouldLeft };
|
|
777
775
|
}
|
|
778
|
-
|
|
776
|
+
|
|
777
|
+
return { hasSynced: false, whatShouldLeft };
|
|
779
778
|
}
|
|
780
779
|
|
|
781
780
|
/**
|
|
@@ -987,19 +986,11 @@ export default class IABookActions extends LitElement {
|
|
|
987
986
|
.lending-wrapper {
|
|
988
987
|
width: 100%;
|
|
989
988
|
margin: 0 auto;
|
|
990
|
-
background: var(--primaryBGColor, #000);
|
|
991
|
-
color: var(--primaryTextColor, #fff);
|
|
992
989
|
display: inline-flex;
|
|
993
990
|
align-items: center;
|
|
994
991
|
justify-content: center;
|
|
995
992
|
flex-wrap: wrap;
|
|
996
993
|
}
|
|
997
|
-
|
|
998
|
-
toast-template {
|
|
999
|
-
--toastTopMargin: 80px;
|
|
1000
|
-
--toastBGColor: #333;
|
|
1001
|
-
--toastFontColor: #fff;
|
|
1002
|
-
}
|
|
1003
994
|
`;
|
|
1004
995
|
}
|
|
1005
996
|
}
|
|
@@ -376,7 +376,8 @@ describe('Browsing expired status', () => {
|
|
|
376
376
|
});
|
|
377
377
|
});
|
|
378
378
|
|
|
379
|
-
describe('Auto renew one hour loan', () => {
|
|
379
|
+
describe('Auto renew one hour loan', async () => {
|
|
380
|
+
await aTimeout(5000);
|
|
380
381
|
it('Book is browsing and renewed it now', async () => {
|
|
381
382
|
const loanTime = 88;
|
|
382
383
|
const el = await fixture(
|
|
@@ -449,6 +450,61 @@ describe('Auto renew one hour loan', () => {
|
|
|
449
450
|
});
|
|
450
451
|
});
|
|
451
452
|
|
|
453
|
+
describe('Visibility change API for document', async () => {
|
|
454
|
+
await aTimeout(5000);
|
|
455
|
+
|
|
456
|
+
beforeEach(() => {
|
|
457
|
+
Object.defineProperty(document, 'hidden', {
|
|
458
|
+
value: false,
|
|
459
|
+
configurable: true,
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
afterEach(() => {
|
|
464
|
+
Object.defineProperty(document, 'hidden', {
|
|
465
|
+
value: true,
|
|
466
|
+
configurable: true,
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('when book is not expired', async () => {
|
|
471
|
+
const el = await fixture(
|
|
472
|
+
container({
|
|
473
|
+
userid: '@user1',
|
|
474
|
+
identifier: 'foobar',
|
|
475
|
+
lendingStatus: {
|
|
476
|
+
user_has_browsed: true,
|
|
477
|
+
browsingExpired: false,
|
|
478
|
+
},
|
|
479
|
+
})
|
|
480
|
+
);
|
|
481
|
+
await el.updateComplete;
|
|
482
|
+
|
|
483
|
+
const spy = Sinon.spy(el, 'loanStatusCheckInterval');
|
|
484
|
+
document.dispatchEvent(new Event('visibilitychange'));
|
|
485
|
+
|
|
486
|
+
expect(spy.calledOnce).to.be.true;
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it('when book is already expired', async () => {
|
|
490
|
+
const el = await fixture(
|
|
491
|
+
container({
|
|
492
|
+
userid: '@user1',
|
|
493
|
+
identifier: 'foobar',
|
|
494
|
+
lendingStatus: {
|
|
495
|
+
user_has_browsed: true,
|
|
496
|
+
},
|
|
497
|
+
})
|
|
498
|
+
);
|
|
499
|
+
await el.updateComplete;
|
|
500
|
+
|
|
501
|
+
const spy = Sinon.spy(el, 'browseHasExpired');
|
|
502
|
+
document.dispatchEvent(new Event('visibilitychange'));
|
|
503
|
+
|
|
504
|
+
expect(spy.calledOnce).to.be.true;
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
|
|
452
508
|
describe('Shared Resize Observer', () => {
|
|
453
509
|
it('can receive a Shared Resize Observer', async () => {
|
|
454
510
|
const sharedObserverStub = new SharedResizeObserver();
|