@internetarchive/ia-book-actions 0.1.9-alpha1 → 0.1.9-alpha3

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
@@ -131,7 +131,7 @@
131
131
  iaBookActions.returnUrl = '';
132
132
  iaBookActions.localCache = localCache;
133
133
 
134
- let loanTotalTime2Min = { loanTotalTime: 10, loanRenewAtLast: 5, pageChangedInLast: 8 };
134
+ let loanTotalTime2Min = { loanTotalTime: 100, loanRenewAtLast: 97, pageChangedInLast: 15 };
135
135
  let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 180, pageChangedInLast: 15 };
136
136
  let loanTotalTime1Hour = { loanTotalTime: 3600, loanRenewAtLast: 660, pageChangedInLast: 900 };
137
137
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "0.1.9-alpha1",
3
+ "version": "0.1.9-alpha3",
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.8",
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"
@@ -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: 3591,
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 Event(event));
87
+ dispatchLoanEvent(event, detail) {
88
+ this.dispatchEvent(new CustomEvent(event, { detail }));
83
89
  }
84
90
 
85
91
  /**
@@ -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 post
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
  *
@@ -25,9 +25,11 @@ export const events = {
25
25
 
26
26
  export const modalButtonStyle = {
27
27
  iaButton:
28
- 'min-height:3rem;cursor:pointer;color:white;border-radius:0.4rem;border:1px solid transparent;padding:4px 8px;',
29
- renew: 'background:#194880;border:1px solid #c5d1df;',
30
- return: 'background:#d9534f;color:white;border:1px solid #c5d1df;',
28
+ 'min-height:3.5rem;cursor:pointer;color:white;border-radius:0.4rem;border:1px solid #c5d1df;padding:4px 8px;width:auto;user-select:none;',
29
+ renew: 'background:#194880;width:110px;',
30
+ return: 'background:#d9534f;',
31
+ loaderIcon:
32
+ 'display:inline-block;width:20px;height:20px;margin-top:2px;color:white; --activityIndicatorLoadingRingColor:#fff;--activityIndicatorLoadingDotColor:#fff;',
31
33
  refresh:
32
34
  'background:none;font-size:inherit;border:0;padding:0;color:#0000ee;cursor:pointer;text-decoration:underline',
33
35
  };
@@ -54,6 +56,7 @@ export default class IABookActions extends LitElement {
54
56
  localCache: { type: Object },
55
57
  loanRenewTimeConfig: { type: Object },
56
58
  loanRenewResult: { type: Object },
59
+ _active: { state: true },
57
60
  };
58
61
  }
59
62
 
@@ -81,10 +84,15 @@ export default class IABookActions extends LitElement {
81
84
  this.secondaryActions = [];
82
85
  this.lendingOptions = {};
83
86
  this.borrowType = ''; // (browsed|borrowed)
84
- this.consecutiveLoanCounts = 1; // consecutive loan count
85
87
  this.suppressToast = false;
86
88
  this.suppressAutoRenew = false;
87
89
  this.browseTimer = undefined;
90
+ this._attemptToRenew = false;
91
+
92
+ /**
93
+ * when user click on [return the book] button on warning modal
94
+ */
95
+ this.returnNow = false;
88
96
 
89
97
  /**
90
98
  * contains one hour auto-loan-renew time configuration
@@ -258,19 +266,13 @@ export default class IABookActions extends LitElement {
258
266
  * Bind 1 hour loan auto renew event,
259
267
  * There are two events we want to use,
260
268
  * 1. BookReader:userAction - dispatched from bookreader side
261
- * 2. click event to refresh the page when book is auto expired
262
- * 3. IABookActions:loanRenew - dispatched from timer-countdown component
269
+ * 2. IABookActions:loanRenew - dispatched from timer-countdown component
263
270
  */
264
271
  bindLoanRenewEvents() {
265
272
  /**
266
273
  * dispatched this event from bookreader page changed
267
274
  */
268
275
  window.addEventListener('BookReader:userAction', () => {
269
- console.log('** BR user Action', {
270
- suppressAutoRenew: this.suppressAutoRenew,
271
- borrowType: this.borrowType,
272
- });
273
-
274
276
  this.suppressToast = true;
275
277
  this.closeToastManager();
276
278
 
@@ -283,28 +285,10 @@ export default class IABookActions extends LitElement {
283
285
  }
284
286
  });
285
287
 
286
- /**
287
- * detect click-event on document to close toast-template
288
- */
289
- document.addEventListener('click', e => {
290
- console.log('*** top level click handler to remove toast on click');
291
- if (this.loanRenewHelper && this.loanRenewResult.secondsLeft > 0) {
292
- this.suppressToast = true;
293
- }
294
-
295
- // reload when user click on book-page and book is EXPIRED
296
- const hasExpired =
297
- 'browsingExpired' in this.lendingStatus &&
298
- this.lendingStatus?.browsingExpired;
299
- if (hasExpired && e.target.nodeName !== 'IA-BOOK-ACTIONS') {
300
- // window.location?.reload();
301
- }
302
- });
303
-
304
288
  /**
305
289
  * this event dispatched from timer-countdown component for:
306
- * 1. user turned book page after showing auto-returned warning message
307
- * 2. show warning message having remaining time
290
+ * 1. user turned book page after showing auto-returned warning modal
291
+ * 2. show warning modal having remaining time
308
292
  * @see TimerCountdown::timerCountdown
309
293
  */
310
294
  this.addEventListener('IABookActions:loanRenew', async event => {
@@ -324,18 +308,16 @@ export default class IABookActions extends LitElement {
324
308
  this.browseHasExpired();
325
309
  }
326
310
 
327
- // show warning message with remaining time to auto returned it.
311
+ // show warning modal with remaining time to auto returned it.
328
312
  if (this.loanRenewResult.renewNow === false) {
329
313
  /**
330
314
  * so compensate for the 50 second buffer to handle above race conditions
331
315
  * let's reduce 1 min from warning texts and early return the book when 1 min left.
332
316
  */
333
317
  secondsLeft -= 60;
334
-
335
318
  this.loanRenewResult.secondsLeft = secondsLeft;
336
319
 
337
- // this.showToastMessage();
338
- this.showModalManager();
320
+ this.showWarningModal();
339
321
  }
340
322
  });
341
323
  }
@@ -360,7 +342,6 @@ export default class IABookActions extends LitElement {
360
342
 
361
343
  /**
362
344
  * create / select the modal-manager component on DOM
363
- *
364
345
  * @memberof IABookActions
365
346
  */
366
347
  async useModalManager() {
@@ -374,9 +355,10 @@ export default class IABookActions extends LitElement {
374
355
  await document.body.appendChild(this.modal);
375
356
  }
376
357
 
377
- async showModalManager(type = '') {
378
- if (this.suppressToast) return;
379
-
358
+ /**
359
+ * Show the waring modal to ask user if they are still reading
360
+ */
361
+ async showWarningModal() {
380
362
  await this.useModalManager();
381
363
 
382
364
  // if secondsLeft < 60, consider it 1 minute
@@ -387,57 +369,79 @@ export default class IABookActions extends LitElement {
387
369
  secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
388
370
  }
389
371
 
390
- let customContent = '';
391
-
392
372
  const config = new ModalConfig();
393
-
394
373
  config.headline = 'Are you still here?';
395
374
  config.showCloseButton = false;
396
375
  config.closeOnBackdropClick = false;
376
+ config.message = this.loanRenewHelper?.getMessageTexts(
377
+ this.loanRenewResult.texts,
378
+ secondsLeft
379
+ );
397
380
 
398
- if (type === 'expired') {
399
- config.message = 'This book has been returned due to inactivity.';
400
- customContent = html`<br />
401
- <div style="text-align: center">
402
- <button
403
- style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
404
- @click=${() => {
405
- window.location?.reload();
406
- }}
407
- >
408
- Okay
409
- </button>
410
- </div> `;
411
- } else {
412
- config.message = this.loanRenewHelper?.getMessageTexts(
413
- this.loanRenewResult.texts,
414
- secondsLeft
415
- );
416
- customContent = html`<br />
417
- <div style="text-align: center">
418
- <button
419
- style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
420
- @click=${() => {
421
- this.autoLoanRenewChecker(true);
422
- }}
423
- >
424
- Keep reading
425
- </button>
426
- <button
427
- style="${modalButtonStyle.iaButton} ${modalButtonStyle.return}"
428
- @click=${() => {
429
- this.dispatchEvent(new CustomEvent('returnNow', {}));
430
- // this.browseHasExpired();
431
- }}
432
- >
433
- Return the book
434
- </button>
435
- </div> `;
436
- }
381
+ const customContent = html`<br />
382
+ <div
383
+ id="custom-buttons"
384
+ style="display:flex;justify-content:center;${this._attemptToRenew
385
+ ? 'pointer-events:none;opacity:0.8'
386
+ : ''}"
387
+ >
388
+ <button
389
+ style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
390
+ @click=${() => {
391
+ console.log('clicked on keep reading button');
392
+ // e.target.parentNode.style.pointerEvents = "none";
393
+ // e.target.parentNode.style.opacity = "0.8";
394
+ this._attemptToRenew = true;
395
+ this.autoLoanRenewChecker(true);
396
+ }}
397
+ >
398
+ ${this._attemptToRenew
399
+ ? html` <ia-activity-indicator
400
+ mode="processing"
401
+ style=${modalButtonStyle.loaderIcon}
402
+ ></ia-activity-indicator>`
403
+ : 'Keep reading'}
404
+ </button>
405
+ <button
406
+ style="${modalButtonStyle.iaButton} ${modalButtonStyle.return}"
407
+ @click=${() => {
408
+ this.returnNow = true;
409
+ }}
410
+ >
411
+ Return the book
412
+ </button>
413
+ </div> `;
437
414
 
438
415
  this.modal.showModal({ config, customModalContent: customContent });
439
416
  }
440
417
 
418
+ /**
419
+ * Show modal when book is auto returned
420
+ */
421
+ async showExpiredModal() {
422
+ await this.useModalManager();
423
+
424
+ const config = new ModalConfig();
425
+ config.headline = '';
426
+ config.showCloseButton = false;
427
+ config.closeOnBackdropClick = false;
428
+ config.message = 'This book has been returned due to inactivity.';
429
+
430
+ const customContent = html`<br />
431
+ <div style="text-align: center">
432
+ <button
433
+ style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
434
+ @click=${() => {
435
+ window.location?.reload();
436
+ }}
437
+ >
438
+ Okay
439
+ </button>
440
+ </div> `;
441
+
442
+ this.modal?.showModal({ config, customModalContent: customContent });
443
+ }
444
+
441
445
  /**
442
446
  * close/hide modal-manager
443
447
  */
@@ -560,11 +564,9 @@ export default class IABookActions extends LitElement {
560
564
  // show message after browsed book is expired.
561
565
  this.loanRenewResult.renewNow = false;
562
566
  this.loanRenewResult.texts =
563
- 'This book has been automatically returned due to inactivity.';
567
+ 'This book has been returned due to inactivity.';
564
568
 
565
- // this.suppressToast = false;
566
- // this.showToastMessage();
567
- this.showModalManager('expired');
569
+ this.showExpiredModal();
568
570
 
569
571
  window?.Sentry?.captureMessage(sentryLogs.browseHasExpired);
570
572
  }
@@ -642,6 +644,7 @@ export default class IABookActions extends LitElement {
642
644
  ?disabled=${this.disableActionGroup}
643
645
  ?autoRenew=${this.loanRenewResult.renewNow}
644
646
  ?autoReturn=${this.lendingStatus.browsingExpired}
647
+ ?returnNow=${this.returnNow}
645
648
  @loanAutoRenewed=${this.handleLoanAutoRenewed}
646
649
  @lendingActionError=${this.handleLendingActionError}
647
650
  @toggleActionGroup=${this.handleToggleActionGroup}
@@ -662,14 +665,14 @@ export default class IABookActions extends LitElement {
662
665
  async handleLoanAutoRenewed(event) {
663
666
  if (this.loanRenewResult.renewNow) {
664
667
  window?.IALendingIntervals?.clearAll();
668
+ this._attemptToRenew = false;
665
669
 
666
670
  this.suppressToast = false;
667
671
  await this.browseHasRenew();
668
- // await this.showToastMessage();
669
672
  await this.resetTimerCountState();
670
673
 
671
674
  // close the modal
672
- await this.modal?.closeModal();
675
+ await this.modal.closeModal();
673
676
 
674
677
  window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
675
678
 
@@ -723,7 +726,7 @@ export default class IABookActions extends LitElement {
723
726
  this.disableActionGroup = !this.disableActionGroup;
724
727
  }
725
728
 
726
- /*
729
+ /**
727
730
  * handle lending errors occure during different operation like
728
731
  * browse book, borrow book, borrowed book token etc...
729
732
  *