@internetarchive/ia-book-actions 0.1.11-b3 → 0.1.11-b31

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
@@ -356,5 +356,6 @@
356
356
  </table>
357
357
  </fieldset>
358
358
  </div>
359
+ <modal-manager></modal-manager>
359
360
  </body>
360
361
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "0.1.11-b3",
3
+ "version": "0.1.11-b31",
4
4
  "description": "Bookreader actions for borrowable book",
5
5
  "author": "Internet Archive",
6
6
  "license": "AGPL-3.0-only",
@@ -21,7 +21,7 @@ export default async function ActionsHandlerService(options) {
21
21
  const tokenError = 'loan token not found. please try again later.';
22
22
  const borrowError =
23
23
  'This book is not available to borrow at this time. Please try again later.';
24
- const erroneousActions = ['browse_book', 'borrow_book', 'create_token'];
24
+ const erroneousActions = ['browse_book', 'borrow_book', 'create_token', 'renew_loan'];
25
25
  const shouldReturnError =
26
26
  location?.href?.indexOf('?error=true') !== -1 &&
27
27
  location?.hostname !== 'archive.org';
@@ -142,7 +142,13 @@ export default class ActionsHandler extends LitElement {
142
142
  action,
143
143
  identifier: this.identifier,
144
144
  success: data => {
145
- console.log("RENEW_LOAN --- ", data, action, data.loan, this.identifier);
145
+ console.log(
146
+ 'RENEW_LOAN --- ',
147
+ data,
148
+ action,
149
+ data.loan,
150
+ this.identifier
151
+ );
146
152
  if (data?.success === true && data?.loan?.renewal === true) {
147
153
  this.setBrowseTimeSession();
148
154
  this.dispatchEvent(
@@ -18,7 +18,7 @@ import { GetLendingActions } from './core/services/get-lending-actions.js';
18
18
  import { mobileContainerWidth } from './core/config/constants.js';
19
19
  import { sentryLogs } from './core/config/sentry-events.js';
20
20
  import { LoanTokenPoller } from './core/services/loan-token-poller.js';
21
- import { LoanRenewHelper } from './core/services/loan-renew-helper.js';
21
+ import { LoanRenewHelper } from './core/services/loan-renew-helper.js'
22
22
 
23
23
  export const events = {
24
24
  browseExpired: 'IABookReader:BrowsingHasExpired',
@@ -77,7 +77,6 @@ export default class IABookActions extends LitElement {
77
77
  this.barType = 'action'; // 'title'|'action'
78
78
  this.sharedObserver = undefined;
79
79
  this.disableActionGroup = false;
80
- this.modal = undefined;
81
80
  this.tokenDelay = 120; // in seconds
82
81
 
83
82
  // private props
@@ -105,7 +104,7 @@ export default class IABookActions extends LitElement {
105
104
  * loanTotalTime: number, - total seconds a loan does have
106
105
  * loanRenewAtLast: number, - check for loan renew at last
107
106
  * pageChangedInLast: number, - consider loan renew eligible if viewed new page
108
- */
107
+ */
109
108
  this.loanRenewTimeConfig = {
110
109
  loanTotalTime: 3600, // 1 hour
111
110
  loanRenewAtLast: 660, // 11 minutes
@@ -257,7 +256,9 @@ export default class IABookActions extends LitElement {
257
256
  // initial timer state for 1-hour loan
258
257
  if (this.borrowType === 'browsed' && !this.loanRenewResult.renewNow) {
259
258
  setTimeout(() => {
260
- console.log('IN TIMEOUT OF --- setupLendingToolbarActions, firing resetTimerCountState');
259
+ console.log(
260
+ 'IN TIMEOUT OF --- setupLendingToolbarActions, firing resetTimerCountState'
261
+ );
261
262
  this.resetTimerCountState();
262
263
  }, 100);
263
264
  }
@@ -306,19 +307,12 @@ export default class IABookActions extends LitElement {
306
307
  this.loanRenewResult = this.loanRenewHelper.result;
307
308
  }
308
309
 
309
- /**
310
- * create / select the modal-manager component on DOM
311
- * @memberof IABookActions
312
- */
313
- async useModalManager() {
314
- if (!this.modal) {
315
- this.modal = document.querySelector('modal-manager');
316
-
317
- if (!this.modal) this.modal = document.createElement('modal-manager');
318
- }
310
+ /** @returns HTMLElement */
311
+ get modal() {
312
+ const modalOnDom = document.querySelector('modal-manager');
319
313
 
320
- this.modal.id = 'action-bar-modal';
321
- await document.body.appendChild(this.modal);
314
+ modalOnDom.id = 'action-bar-modal';
315
+ return modalOnDom;
322
316
  }
323
317
 
324
318
  /**
@@ -326,7 +320,11 @@ export default class IABookActions extends LitElement {
326
320
  */
327
321
  async showWarningModal() {
328
322
  console.log('****** showWarningModal ******');
329
- await this.useModalManager();
323
+ // clear modal
324
+ this.modal.customModalContent = nothing;
325
+ this.modal?.closeModal();
326
+ console.log("MODAL CLOSED ___ ", this.modal.customModalContent);
327
+ this.loanRenewResult = { texts: '', renewNow: false };
330
328
 
331
329
  // if secondsLeft < 60, consider it 1 minute
332
330
  let { secondsLeft } = this.loanRenewResult;
@@ -336,30 +334,28 @@ export default class IABookActions extends LitElement {
336
334
  secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
337
335
  }
338
336
 
339
- const config = new ModalConfig();
340
- config.headline = 'Are you still here?';
341
- config.showCloseButton = false;
342
- config.closeOnBackdropClick = false;
343
- config.message = this.loanRenewHelper?.getMessageTexts(
344
- this.loanRenewResult.texts,
345
- secondsLeft
346
- );
337
+ const config = new ModalConfig({
338
+ headline: 'Are you still here?',
339
+ showCloseButton: false,
340
+ closeOnBackdropClick: false,
341
+ message: this.loanRenewHelper?.getMessageTexts(
342
+ this.loanRenewResult.texts,
343
+ secondsLeft
344
+ )
345
+ });
347
346
 
348
- const customContent = html`<br />
349
- <div id="custom-buttons" style="display:flex;justify-content:center;">
347
+ const customModalContent = html`<br />
348
+ <div id="book-action-bar-custom-buttons" style="display:flex;justify-content:center;">
350
349
  <button
351
350
  style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
352
- @click=${async event => {
353
- await this.changeModalState(event);
354
- this.loanRenewResult = { texts: '', renewNow: true };
355
- }}
351
+ @click=${event => this.patronWantsToRenewBook(event)}
356
352
  >
357
353
  Keep reading
358
354
  </button>
359
355
  <button
360
356
  style="${modalButtonStyle.iaButton} ${modalButtonStyle.return}"
361
- @click=${event => {
362
- this.changeModalState(event);
357
+ @click=${() => {
358
+ // this.changeModalState(event);
363
359
  document.querySelector('ia-book-actions').disableActionGroup = true;
364
360
  this.returnNow = true;
365
361
  }}
@@ -368,7 +364,77 @@ export default class IABookActions extends LitElement {
368
364
  </button>
369
365
  </div> `;
370
366
 
371
- this.modal?.showModal({ config, customModalContent: customContent });
367
+
368
+ await this.modal?.showModal({ config, customModalContent });
369
+ }
370
+
371
+ async showWarningDisabledModal() {
372
+ console.log('****** showWarningDisabledModal ******');
373
+
374
+ // if secondsLeft < 60, consider it 1 minute
375
+ let { secondsLeft } = this.loanRenewResult;
376
+ if (secondsLeft === undefined) {
377
+ secondsLeft = this.lendingStatus.secondsLeftOnLoan;
378
+ } else {
379
+ secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
380
+ }
381
+
382
+ const config = new ModalConfig({
383
+ headline: 'Are you still here?',
384
+ showCloseButton: false,
385
+ closeOnBackdropClick: false,
386
+ message: this.loanRenewHelper?.getMessageTexts(
387
+ this.loanRenewResult.texts,
388
+ secondsLeft
389
+ )
390
+ });
391
+
392
+
393
+ // this doesn't really work? shows empty button
394
+
395
+ // if (event.target === undefined) return;
396
+
397
+ // const button = event.target;
398
+ // button.disabled = true;
399
+ // button.innerHTML = `<ia-activity-indicator
400
+ // mode="processing"
401
+ // style=${modalButtonStyle.loaderIcon}
402
+ // ></ia-activity-indicator>`;
403
+
404
+ // const parentElement = event.target.parentNode;
405
+ // parentElement.style.pointerEvents = 'none';
406
+ // parentElement.style.opacity = 0.8;
407
+
408
+
409
+ const customModalContent = html`<br />
410
+ <div id="disabled-book-action-bar-custom-buttons" style="display:flex;justify-content:center; opacity:0.8; pointer-events:none;">
411
+ <button
412
+ disabled
413
+ style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
414
+ >
415
+ <ia-activity-indicator
416
+ mode="processing"
417
+ style=${modalButtonStyle.loaderIcon}
418
+ ></ia-activity-indicator>
419
+ </button>
420
+ <button
421
+ disabled
422
+ style="${modalButtonStyle.iaButton} ${modalButtonStyle.return}"
423
+ >
424
+ Return the book
425
+ </button>
426
+ </div> `;
427
+
428
+ await this.modal?.showModal({ config, customModalContent });
429
+ }
430
+
431
+
432
+
433
+ async patronWantsToRenewBook(event) {
434
+ // this.changeModalState(event);
435
+ console.log("patron wants to renew book!!!!", this.loanRenewResult);
436
+ this.loanRenewResult = { texts: '', renewNow: true };
437
+ console.log("patron wants to renew book!!!! loanRenewResult set as: ", this.loanRenewResult);
372
438
  }
373
439
 
374
440
  /**
@@ -378,18 +444,22 @@ export default class IABookActions extends LitElement {
378
444
  *
379
445
  * @param {Event} event
380
446
  */
381
- changeModalState(event) {
382
- if (event.target === undefined) return;
383
-
384
- const button = event.target;
385
- button.innerHTML = `<ia-activity-indicator
386
- mode="processing"
387
- style=${modalButtonStyle.loaderIcon}
388
- ></ia-activity-indicator>`;
389
-
390
- const parentElement = event.target.parentNode;
391
- parentElement.style.pointerEvents = 'none';
392
- parentElement.style.opacity = 0.8;
447
+ changeModalState() {
448
+ this.showWarningDisabledModal();
449
+ // this doesn't really work? shows empty button
450
+
451
+ // if (event.target === undefined) return;
452
+
453
+ // const button = event.target;
454
+ // button.disabled = true;
455
+ // button.innerHTML = `<ia-activity-indicator
456
+ // mode="processing"
457
+ // style=${modalButtonStyle.loaderIcon}
458
+ // ></ia-activity-indicator>`;
459
+
460
+ // const parentElement = event.target.parentNode;
461
+ // parentElement.style.pointerEvents = 'none';
462
+ // parentElement.style.opacity = 0.8;
393
463
  }
394
464
 
395
465
  /**
@@ -397,15 +467,15 @@ export default class IABookActions extends LitElement {
397
467
  */
398
468
  async showExpiredModal() {
399
469
  console.log('showExpiredModal()');
400
- await this.useModalManager();
401
470
 
402
- const config = new ModalConfig();
403
- config.headline = '';
404
- config.showCloseButton = false;
405
- config.closeOnBackdropClick = false;
406
- config.message = 'This book has been returned due to inactivity.';
471
+ const config = new ModalConfig({
472
+ headline: '',
473
+ showCloseButton: false,
474
+ closeOnBackdropClick: false,
475
+ message: 'This book has been returned due to inactivity.'
476
+ });
407
477
 
408
- const customContent = html`<br />
478
+ const customModalContent = html`<br />
409
479
  <div style="text-align: center">
410
480
  <button
411
481
  style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
@@ -417,15 +487,7 @@ export default class IABookActions extends LitElement {
417
487
  </button>
418
488
  </div> `;
419
489
 
420
- this.modal?.showModal({ config, customModalContent: customContent });
421
- }
422
-
423
- /**
424
- * close/hide modal-manager
425
- */
426
- async closeModalManager() {
427
- this.modal = document.querySelector('modal-manager');
428
- this.modal?.closeModal();
490
+ await this.modal?.showModal({ config, customModalContent });
429
491
  }
430
492
 
431
493
  /**
@@ -508,7 +570,11 @@ export default class IABookActions extends LitElement {
508
570
 
509
571
  async startBrowseTimer() {
510
572
  clearTimeout(this.browseTimer);
511
- console.log('startBrowseTimerstartBrowseTimer just cleared timer', this.browseTimer, this.lendingStatus);
573
+ console.log(
574
+ 'startBrowseTimerstartBrowseTimer just cleared timer',
575
+ this.browseTimer,
576
+ this.lendingStatus
577
+ );
512
578
 
513
579
  const {
514
580
  browsingExpired,
@@ -521,7 +587,10 @@ export default class IABookActions extends LitElement {
521
587
  }
522
588
 
523
589
  this.browseTimer = setTimeout(() => {
524
- console.log('start `this.browseTimer will fire his.browseHasExpired() - secondsLeftOnLoan', secondsLeftOnLoan);
590
+ console.log(
591
+ 'start `this.browseTimer will fire his.browseHasExpired() - secondsLeftOnLoan',
592
+ secondsLeftOnLoan
593
+ );
525
594
  this.browseHasExpired();
526
595
  }, secondsLeftOnLoan * 1000);
527
596
  }
@@ -533,11 +602,22 @@ export default class IABookActions extends LitElement {
533
602
  const timerCountdown = this._shadowRoot.querySelector('timer-countdown');
534
603
  if (!timerCountdown) return;
535
604
 
536
- const secondsLeft = Number.parseInt((Number(this.lendingStatus.secondsLeftOnLoan)), 10);
537
- const strokeDashOffset =
538
- (secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315;
605
+ const secondsLeft = Number.parseInt(
606
+ Number(this.lendingStatus.secondsLeftOnLoan),
607
+ 10
608
+ );
609
+ const firstStrokeDashOffset = Number.parseInt(
610
+ (secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315 * 1.5,
611
+ 10
612
+ );
613
+ const actualStrokeDashOffset =
614
+ firstStrokeDashOffset > 315 ? 315 : firstStrokeDashOffset;
539
615
 
540
- console.log('resetTimerCountState === ', { secondsLeft, strokeDashOffset});
616
+ console.log('resetTimerCountState === ', {
617
+ secondsLeft,
618
+ firstStrokeDashOffset,
619
+ actualStrokeDashOffset,
620
+ });
541
621
 
542
622
  // set seconds left in loan expire
543
623
  timerCountdown.style?.setProperty('--secondsLeftOnLoan', `${secondsLeft}s`);
@@ -545,7 +625,7 @@ export default class IABookActions extends LitElement {
545
625
  // set circle stroke offset left in loan expire
546
626
  timerCountdown.style?.setProperty(
547
627
  '--strokeLeftOnLoan',
548
- `${Number(strokeDashOffset)}` // the perimeter of the circle = (π * 2 * radius)
628
+ `${actualStrokeDashOffset}` // the perimeter of the circle = (π * 2 * radius)
549
629
  );
550
630
 
551
631
  const animationCircle = timerCountdown.shadowRoot.querySelector('.circle');
@@ -574,14 +654,6 @@ export default class IABookActions extends LitElement {
574
654
  ></book-title-bar>`;
575
655
  }
576
656
 
577
- get timerCountdownTemplate() {
578
- return this.borrowType === 'browsed'
579
- ? html`<timer-countdown
580
- .secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
581
- ></timer-countdown>`
582
- : nothing;
583
- }
584
-
585
657
  get bookActionBar() {
586
658
  return html`
587
659
  <collapsible-action-group
@@ -606,7 +678,10 @@ export default class IABookActions extends LitElement {
606
678
  >
607
679
  </collapsible-action-group>
608
680
  ${this.textGroupTemplate} ${this.infoIconTemplate}
609
- ${this.timerCountdownTemplate}
681
+ <timer-countdown
682
+ .secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
683
+ class=${this.borrowType === 'browsed' ? '' : 'hide'}
684
+ ></timer-countdown>
610
685
  `;
611
686
  }
612
687
 
@@ -628,11 +703,10 @@ export default class IABookActions extends LitElement {
628
703
  secondsLeftOnLoan: Math.round(this.lendingStatus.secondsLeftOnLoan), // stale? how to fix
629
704
  });
630
705
 
631
-
632
706
  // Now, let's reset loan duration & this.lendingStatus
633
707
  const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
634
708
  const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
635
-
709
+
636
710
  const currStatus = {
637
711
  ...this.lendingStatus,
638
712
  user_has_browsed: true,
@@ -642,17 +716,23 @@ export default class IABookActions extends LitElement {
642
716
  this.lendingStatus = currStatus;
643
717
 
644
718
  console.log('~~~ handleLoanAutoRenewed - new this.lendingStatus', {
645
- secondsLeftOnLoan: this.lendingStatus.secondsLeftOnLoan
719
+ secondsLeftOnLoan: this.lendingStatus.secondsLeftOnLoan,
646
720
  });
647
-
721
+
648
722
  /**
649
723
  * reset timer countdown states
650
724
  */
651
725
  await this.resetTimerCountState();
652
726
 
653
727
  // close the modal
654
- this.modal?.remove();
655
- this.modal?.showModal({ config: {}, customModalContent: `` });
728
+ this.modal.removeAttribute('id');
729
+ // const editedActionButtons = this.modal.shadowRoot.querySelector('#book-action-bar-custom-buttons');
730
+ // if (editedActionButtons) {
731
+ // editedActionButtons.parentElement.removeChild(editedActionButtons);
732
+ // }
733
+ this.modal.customModalContent = nothing;
734
+ this.modal?.closeModal();
735
+ console.log("MODAL CLOSED ___ ", this.modal.customModalContent);
656
736
 
657
737
  window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
658
738
  }
@@ -679,7 +759,10 @@ export default class IABookActions extends LitElement {
679
759
  // if really updated, escape from here
680
760
  const resync = await this.reSyncTimerIfGoneOff(secondsLeft);
681
761
 
682
- console.log("*** startTimerCountdown = reSyncTimerIfGoneOff ***", { secondsLeft, resync });
762
+ console.log('*** startTimerCountdown = reSyncTimerIfGoneOff ***', {
763
+ secondsLeft,
764
+ resync,
765
+ });
683
766
 
684
767
  if (resync) {
685
768
  console.log('have resyncd, will end startTimerCountdown here - ');
@@ -887,7 +970,6 @@ export default class IABookActions extends LitElement {
887
970
 
888
971
  /* show error message if something went wrong */
889
972
  async showErrorModal(errorMsg, action) {
890
- await this.useModalManager();
891
973
 
892
974
  const modalConfig = new ModalConfig({
893
975
  title: 'Lending error',
@@ -915,7 +997,7 @@ export default class IABookActions extends LitElement {
915
997
  <code>errorLog: ${errorMsg}</code>`;
916
998
  }
917
999
 
918
- this.modal?.showModal({
1000
+ await this.modal?.showModal({
919
1001
  config: modalConfig,
920
1002
  });
921
1003
  }
@@ -952,6 +1034,10 @@ export default class IABookActions extends LitElement {
952
1034
  display: block;
953
1035
  }
954
1036
 
1037
+ .hide {
1038
+ display: none;
1039
+ }
1040
+
955
1041
  .lending-wrapper {
956
1042
  width: 100%;
957
1043
  margin: 0 auto;