@internetarchive/ia-book-actions 1.1.0-alpha13 → 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,21 +292,35 @@ 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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
this.
|
|
308
|
-
this.
|
|
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);
|
|
317
|
+
|
|
318
|
+
if (secondsLeft >= this.timerExecutionSeconds) {
|
|
319
|
+
this.loanStatusCheckInterval(Number(secondsLeft));
|
|
320
|
+
} else {
|
|
321
|
+
this.browseHasExpired();
|
|
322
|
+
this.disconnectedCallback();
|
|
323
|
+
}
|
|
309
324
|
}
|
|
310
325
|
}
|
|
311
326
|
});
|
|
@@ -488,31 +503,6 @@ export default class IABookActions extends LitElement {
|
|
|
488
503
|
await this.modal?.showModal({ config, customModalContent });
|
|
489
504
|
}
|
|
490
505
|
|
|
491
|
-
/**
|
|
492
|
-
* @deprecated
|
|
493
|
-
* create / select the toast-template component on DOM
|
|
494
|
-
*
|
|
495
|
-
* @memberof IABookActions
|
|
496
|
-
*/
|
|
497
|
-
async useToastManager() {
|
|
498
|
-
if (!this.toast) {
|
|
499
|
-
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
500
|
-
|
|
501
|
-
if (!this.toast) this.toast = document.createElement('toast-template');
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
await this.shadowRoot.appendChild(this.toast);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* @deprecated
|
|
509
|
-
* close/hide toast message
|
|
510
|
-
*/
|
|
511
|
-
async closeToastManager() {
|
|
512
|
-
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
513
|
-
this.toast?.remove();
|
|
514
|
-
}
|
|
515
|
-
|
|
516
506
|
/**
|
|
517
507
|
* Execute when loan is expired
|
|
518
508
|
*/
|
|
@@ -641,7 +631,10 @@ export default class IABookActions extends LitElement {
|
|
|
641
631
|
if (this.loanRenewResult.renewNow) {
|
|
642
632
|
// Now, let's reset loan duration & this.lendingStatus
|
|
643
633
|
const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
|
|
644
|
-
|
|
634
|
+
|
|
635
|
+
// number of seconds left in current loan
|
|
636
|
+
const secondsLeft = Math.round((loanTime - new Date()) / 1000);
|
|
637
|
+
log(loanTime, secondsLeft);
|
|
645
638
|
|
|
646
639
|
log('IABookActions: handleLoanAutoRenewed --- ', {
|
|
647
640
|
ajaxResponse: detail?.data,
|
|
@@ -678,7 +671,7 @@ export default class IABookActions extends LitElement {
|
|
|
678
671
|
|
|
679
672
|
window.IALendingIntervals.timerCountdown = setInterval(async () => {
|
|
680
673
|
// interval execution block
|
|
681
|
-
await this.
|
|
674
|
+
await this.loanStatusCheckInterval(secondsLeft);
|
|
682
675
|
}, this.timerExecutionSeconds * 1000);
|
|
683
676
|
}
|
|
684
677
|
|
|
@@ -687,10 +680,10 @@ export default class IABookActions extends LitElement {
|
|
|
687
680
|
* - if setInterval timer gone off, let's resync
|
|
688
681
|
* - loan-renew attempt to renew the loan OR show relavant message
|
|
689
682
|
* - if loan has expired, clear interval timers
|
|
690
|
-
*
|
|
691
|
-
* @param {Number} secondsLeftOnLoan
|
|
683
|
+
*
|
|
684
|
+
* @param {Number} secondsLeftOnLoan
|
|
692
685
|
*/
|
|
693
|
-
async
|
|
686
|
+
async loanStatusCheckInterval(secondsLeftOnLoan) {
|
|
694
687
|
let secondsLeft = secondsLeftOnLoan;
|
|
695
688
|
secondsLeft -= this.timerExecutionSeconds;
|
|
696
689
|
secondsLeft = Math.round(secondsLeft); // round number
|
|
@@ -700,21 +693,30 @@ export default class IABookActions extends LitElement {
|
|
|
700
693
|
// if really updated, escape from here
|
|
701
694
|
const resyncd = await this.reSyncTimerIfGoneOff(secondsLeft);
|
|
702
695
|
|
|
703
|
-
if (resyncd
|
|
696
|
+
if (resyncd.hasSynced) {
|
|
704
697
|
secondsLeft = resyncd.whatShouldLeft;
|
|
705
698
|
log('startTimerCountdown --- stale, timer has resyncd', {
|
|
706
699
|
secondsLeft,
|
|
707
700
|
});
|
|
708
701
|
}
|
|
709
702
|
|
|
710
|
-
log(
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
+
);
|
|
715
717
|
|
|
716
718
|
/**
|
|
717
|
-
* execute from last 10th
|
|
719
|
+
* execute from last 10th minutes to 0th minute
|
|
718
720
|
* - 10th - to check if user has viewed
|
|
719
721
|
* - till 0th - to show warning msg with remaining time to auto expired
|
|
720
722
|
* @see IABookActions::bindLoanRenewEvents
|
|
@@ -734,8 +736,7 @@ export default class IABookActions extends LitElement {
|
|
|
734
736
|
* helper function to determine if timer is not in sync properly
|
|
735
737
|
*
|
|
736
738
|
* @param {number} timerSecondsLeft - actual seconds left get from setInterval
|
|
737
|
-
*
|
|
738
|
-
* @memberof TimerCountdown
|
|
739
|
+
* @returns {Object} { hasSynced: [boolean], whatShouldLeft: [number] }
|
|
739
740
|
*/
|
|
740
741
|
async reSyncTimerIfGoneOff(timerSecondsLeft) {
|
|
741
742
|
const currentTime = new Date();
|
|
@@ -770,10 +771,10 @@ export default class IABookActions extends LitElement {
|
|
|
770
771
|
|
|
771
772
|
if (whatIsleft !== whatShouldLeft) {
|
|
772
773
|
log(`reSyncTimerIfGoneOff --- let's re-sync.`);
|
|
773
|
-
|
|
774
774
|
return { hasSynced: true, whatShouldLeft };
|
|
775
775
|
}
|
|
776
|
-
|
|
776
|
+
|
|
777
|
+
return { hasSynced: false, whatShouldLeft };
|
|
777
778
|
}
|
|
778
779
|
|
|
779
780
|
/**
|
|
@@ -985,19 +986,11 @@ export default class IABookActions extends LitElement {
|
|
|
985
986
|
.lending-wrapper {
|
|
986
987
|
width: 100%;
|
|
987
988
|
margin: 0 auto;
|
|
988
|
-
background: var(--primaryBGColor, #000);
|
|
989
|
-
color: var(--primaryTextColor, #fff);
|
|
990
989
|
display: inline-flex;
|
|
991
990
|
align-items: center;
|
|
992
991
|
justify-content: center;
|
|
993
992
|
flex-wrap: wrap;
|
|
994
993
|
}
|
|
995
|
-
|
|
996
|
-
toast-template {
|
|
997
|
-
--toastTopMargin: 80px;
|
|
998
|
-
--toastBGColor: #333;
|
|
999
|
-
--toastFontColor: #fff;
|
|
1000
|
-
}
|
|
1001
994
|
`;
|
|
1002
995
|
}
|
|
1003
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();
|