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

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-b30",
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
+
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,76 @@ export default class IABookActions extends LitElement {
368
364
  </button>
369
365
  </div> `;
370
366
 
371
- this.modal?.showModal({ config, customModalContent: customContent });
367
+ await this.modal?.showModal({ config, customModalContent });
368
+ }
369
+
370
+ async showWarningDisabledModal() {
371
+ console.log('****** showWarningDisabledModal ******');
372
+
373
+ // if secondsLeft < 60, consider it 1 minute
374
+ let { secondsLeft } = this.loanRenewResult;
375
+ if (secondsLeft === undefined) {
376
+ secondsLeft = this.lendingStatus.secondsLeftOnLoan;
377
+ } else {
378
+ secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
379
+ }
380
+
381
+ const config = new ModalConfig({
382
+ headline: 'Are you still here?',
383
+ showCloseButton: false,
384
+ closeOnBackdropClick: false,
385
+ message: this.loanRenewHelper?.getMessageTexts(
386
+ this.loanRenewResult.texts,
387
+ secondsLeft
388
+ )
389
+ });
390
+
391
+
392
+ // this doesn't really work? shows empty button
393
+
394
+ // if (event.target === undefined) return;
395
+
396
+ // const button = event.target;
397
+ // button.disabled = true;
398
+ // button.innerHTML = `<ia-activity-indicator
399
+ // mode="processing"
400
+ // style=${modalButtonStyle.loaderIcon}
401
+ // ></ia-activity-indicator>`;
402
+
403
+ // const parentElement = event.target.parentNode;
404
+ // parentElement.style.pointerEvents = 'none';
405
+ // parentElement.style.opacity = 0.8;
406
+
407
+
408
+ const customModalContent = html`<br />
409
+ <div id="disabled-book-action-bar-custom-buttons" style="display:flex;justify-content:center; opacity:0.8; pointer-events:none;">
410
+ <button
411
+ disabled
412
+ style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
413
+ >
414
+ <ia-activity-indicator
415
+ mode="processing"
416
+ style=${modalButtonStyle.loaderIcon}
417
+ ></ia-activity-indicator>
418
+ </button>
419
+ <button
420
+ disabled
421
+ style="${modalButtonStyle.iaButton} ${modalButtonStyle.return}"
422
+ >
423
+ Return the book
424
+ </button>
425
+ </div> `;
426
+
427
+ await this.modal?.showModal({ config, customModalContent });
428
+ }
429
+
430
+
431
+
432
+ async patronWantsToRenewBook(event) {
433
+ // this.changeModalState(event);
434
+ console.log("patron wants to renew book!!!!", this.loanRenewResult);
435
+ this.loanRenewResult = { texts: '', renewNow: true };
436
+ console.log("patron wants to renew book!!!! loanRenewResult set as: ", this.loanRenewResult);
372
437
  }
373
438
 
374
439
  /**
@@ -378,18 +443,22 @@ export default class IABookActions extends LitElement {
378
443
  *
379
444
  * @param {Event} event
380
445
  */
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;
446
+ changeModalState() {
447
+ this.showWarningDisabledModal();
448
+ // this doesn't really work? shows empty button
449
+
450
+ // if (event.target === undefined) return;
451
+
452
+ // const button = event.target;
453
+ // button.disabled = true;
454
+ // button.innerHTML = `<ia-activity-indicator
455
+ // mode="processing"
456
+ // style=${modalButtonStyle.loaderIcon}
457
+ // ></ia-activity-indicator>`;
458
+
459
+ // const parentElement = event.target.parentNode;
460
+ // parentElement.style.pointerEvents = 'none';
461
+ // parentElement.style.opacity = 0.8;
393
462
  }
394
463
 
395
464
  /**
@@ -397,15 +466,15 @@ export default class IABookActions extends LitElement {
397
466
  */
398
467
  async showExpiredModal() {
399
468
  console.log('showExpiredModal()');
400
- await this.useModalManager();
401
469
 
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.';
470
+ const config = new ModalConfig({
471
+ headline: '',
472
+ showCloseButton: false,
473
+ closeOnBackdropClick: false,
474
+ message: 'This book has been returned due to inactivity.'
475
+ });
407
476
 
408
- const customContent = html`<br />
477
+ const customModalContent = html`<br />
409
478
  <div style="text-align: center">
410
479
  <button
411
480
  style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
@@ -417,15 +486,7 @@ export default class IABookActions extends LitElement {
417
486
  </button>
418
487
  </div> `;
419
488
 
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();
489
+ await this.modal?.showModal({ config, customModalContent });
429
490
  }
430
491
 
431
492
  /**
@@ -508,7 +569,11 @@ export default class IABookActions extends LitElement {
508
569
 
509
570
  async startBrowseTimer() {
510
571
  clearTimeout(this.browseTimer);
511
- console.log('startBrowseTimerstartBrowseTimer just cleared timer', this.browseTimer, this.lendingStatus);
572
+ console.log(
573
+ 'startBrowseTimerstartBrowseTimer just cleared timer',
574
+ this.browseTimer,
575
+ this.lendingStatus
576
+ );
512
577
 
513
578
  const {
514
579
  browsingExpired,
@@ -521,7 +586,10 @@ export default class IABookActions extends LitElement {
521
586
  }
522
587
 
523
588
  this.browseTimer = setTimeout(() => {
524
- console.log('start `this.browseTimer will fire his.browseHasExpired() - secondsLeftOnLoan', secondsLeftOnLoan);
589
+ console.log(
590
+ 'start `this.browseTimer will fire his.browseHasExpired() - secondsLeftOnLoan',
591
+ secondsLeftOnLoan
592
+ );
525
593
  this.browseHasExpired();
526
594
  }, secondsLeftOnLoan * 1000);
527
595
  }
@@ -533,11 +601,22 @@ export default class IABookActions extends LitElement {
533
601
  const timerCountdown = this._shadowRoot.querySelector('timer-countdown');
534
602
  if (!timerCountdown) return;
535
603
 
536
- const secondsLeft = Number.parseInt((Number(this.lendingStatus.secondsLeftOnLoan)), 10);
537
- const strokeDashOffset =
538
- (secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315;
604
+ const secondsLeft = Number.parseInt(
605
+ Number(this.lendingStatus.secondsLeftOnLoan),
606
+ 10
607
+ );
608
+ const firstStrokeDashOffset = Number.parseInt(
609
+ (secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315 * 1.5,
610
+ 10
611
+ );
612
+ const actualStrokeDashOffset =
613
+ firstStrokeDashOffset > 315 ? 315 : firstStrokeDashOffset;
539
614
 
540
- console.log('resetTimerCountState === ', { secondsLeft, strokeDashOffset});
615
+ console.log('resetTimerCountState === ', {
616
+ secondsLeft,
617
+ firstStrokeDashOffset,
618
+ actualStrokeDashOffset,
619
+ });
541
620
 
542
621
  // set seconds left in loan expire
543
622
  timerCountdown.style?.setProperty('--secondsLeftOnLoan', `${secondsLeft}s`);
@@ -545,7 +624,7 @@ export default class IABookActions extends LitElement {
545
624
  // set circle stroke offset left in loan expire
546
625
  timerCountdown.style?.setProperty(
547
626
  '--strokeLeftOnLoan',
548
- `${Number(strokeDashOffset)}` // the perimeter of the circle = (π * 2 * radius)
627
+ `${actualStrokeDashOffset}` // the perimeter of the circle = (π * 2 * radius)
549
628
  );
550
629
 
551
630
  const animationCircle = timerCountdown.shadowRoot.querySelector('.circle');
@@ -574,14 +653,6 @@ export default class IABookActions extends LitElement {
574
653
  ></book-title-bar>`;
575
654
  }
576
655
 
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
656
  get bookActionBar() {
586
657
  return html`
587
658
  <collapsible-action-group
@@ -606,7 +677,10 @@ export default class IABookActions extends LitElement {
606
677
  >
607
678
  </collapsible-action-group>
608
679
  ${this.textGroupTemplate} ${this.infoIconTemplate}
609
- ${this.timerCountdownTemplate}
680
+ <timer-countdown
681
+ .secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
682
+ class=${this.borrowType === 'browsed' ? '' : 'hide'}
683
+ ></timer-countdown>
610
684
  `;
611
685
  }
612
686
 
@@ -628,11 +702,10 @@ export default class IABookActions extends LitElement {
628
702
  secondsLeftOnLoan: Math.round(this.lendingStatus.secondsLeftOnLoan), // stale? how to fix
629
703
  });
630
704
 
631
-
632
705
  // Now, let's reset loan duration & this.lendingStatus
633
706
  const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
634
707
  const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
635
-
708
+
636
709
  const currStatus = {
637
710
  ...this.lendingStatus,
638
711
  user_has_browsed: true,
@@ -642,17 +715,23 @@ export default class IABookActions extends LitElement {
642
715
  this.lendingStatus = currStatus;
643
716
 
644
717
  console.log('~~~ handleLoanAutoRenewed - new this.lendingStatus', {
645
- secondsLeftOnLoan: this.lendingStatus.secondsLeftOnLoan
718
+ secondsLeftOnLoan: this.lendingStatus.secondsLeftOnLoan,
646
719
  });
647
-
720
+
648
721
  /**
649
722
  * reset timer countdown states
650
723
  */
651
724
  await this.resetTimerCountState();
652
725
 
653
726
  // close the modal
654
- this.modal?.remove();
655
- this.modal?.showModal({ config: {}, customModalContent: `` });
727
+ this.modal.removeAttribute('id');
728
+ // const editedActionButtons = this.modal.shadowRoot.querySelector('#book-action-bar-custom-buttons');
729
+ // if (editedActionButtons) {
730
+ // editedActionButtons.parentElement.removeChild(editedActionButtons);
731
+ // }
732
+ this.modal.customModalContent = nothing;
733
+ this.modal?.closeModal();
734
+ console.log("MODAL CLOSED ___ ", this.modal.customModalContent);
656
735
 
657
736
  window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
658
737
  }
@@ -679,7 +758,10 @@ export default class IABookActions extends LitElement {
679
758
  // if really updated, escape from here
680
759
  const resync = await this.reSyncTimerIfGoneOff(secondsLeft);
681
760
 
682
- console.log("*** startTimerCountdown = reSyncTimerIfGoneOff ***", { secondsLeft, resync });
761
+ console.log('*** startTimerCountdown = reSyncTimerIfGoneOff ***', {
762
+ secondsLeft,
763
+ resync,
764
+ });
683
765
 
684
766
  if (resync) {
685
767
  console.log('have resyncd, will end startTimerCountdown here - ');
@@ -887,7 +969,6 @@ export default class IABookActions extends LitElement {
887
969
 
888
970
  /* show error message if something went wrong */
889
971
  async showErrorModal(errorMsg, action) {
890
- await this.useModalManager();
891
972
 
892
973
  const modalConfig = new ModalConfig({
893
974
  title: 'Lending error',
@@ -915,7 +996,7 @@ export default class IABookActions extends LitElement {
915
996
  <code>errorLog: ${errorMsg}</code>`;
916
997
  }
917
998
 
918
- this.modal?.showModal({
999
+ await this.modal?.showModal({
919
1000
  config: modalConfig,
920
1001
  });
921
1002
  }
@@ -952,6 +1033,10 @@ export default class IABookActions extends LitElement {
952
1033
  display: block;
953
1034
  }
954
1035
 
1036
+ .hide {
1037
+ display: none;
1038
+ }
1039
+
955
1040
  .lending-wrapper {
956
1041
  width: 100%;
957
1042
  margin: 0 auto;