@internetarchive/ia-book-actions 0.1.11-b2 → 0.1.11-b20

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-b2",
3
+ "version": "0.1.11-b20",
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(
@@ -300,6 +306,7 @@ export default class ActionsHandler extends LitElement {
300
306
  * set browse time in indexedDB
301
307
  */
302
308
  async setBrowseTimeSession() {
309
+ // TODO: USE loan info to determine what we have left
303
310
  try {
304
311
  const expireDate = new Date(
305
312
  new Date().getTime() + this.loanTotalTime * 1000
@@ -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
@@ -100,13 +99,17 @@ export default class IABookActions extends LitElement {
100
99
 
101
100
  /**
102
101
  * contains one hour auto-loan-renew time configuration
103
- *
104
- * @type {object} loanRenewTimeConfig
105
- * @property {number} loanTotalTime - total seconds a loan does have
106
- * @property {number} loanRenewAtLast - check for loan renew at last
107
- * @property {number} pageChangedInLast - consider loan renew eligible if viewed new page
102
+ * defaults to 1 hour config
103
+ * @type {{
104
+ * loanTotalTime: number, - total seconds a loan does have
105
+ * loanRenewAtLast: number, - check for loan renew at last
106
+ * pageChangedInLast: number, - consider loan renew eligible if viewed new page
108
107
  */
109
- this.loanRenewTimeConfig = {};
108
+ this.loanRenewTimeConfig = {
109
+ loanTotalTime: 3600, // 1 hour
110
+ loanRenewAtLast: 660, // 11 minutes
111
+ pageChangedInLast: 900, // 15 minutes
112
+ };
110
113
 
111
114
  /**
112
115
  * contains one hour auto-loan-renew response
@@ -253,6 +256,9 @@ export default class IABookActions extends LitElement {
253
256
  // initial timer state for 1-hour loan
254
257
  if (this.borrowType === 'browsed' && !this.loanRenewResult.renewNow) {
255
258
  setTimeout(() => {
259
+ console.log(
260
+ 'IN TIMEOUT OF --- setupLendingToolbarActions, firing resetTimerCountState'
261
+ );
256
262
  this.resetTimerCountState();
257
263
  }, 100);
258
264
  }
@@ -301,19 +307,12 @@ export default class IABookActions extends LitElement {
301
307
  this.loanRenewResult = this.loanRenewHelper.result;
302
308
  }
303
309
 
304
- /**
305
- * create / select the modal-manager component on DOM
306
- * @memberof IABookActions
307
- */
308
- async useModalManager() {
309
- if (!this.modal) {
310
- this.modal = document.querySelector('modal-manager');
311
-
312
- if (!this.modal) this.modal = document.createElement('modal-manager');
313
- }
310
+ /** @returns HTMLElement */
311
+ get modal() {
312
+ const modalOnDom = document.querySelector('modal-manager');
314
313
 
315
- this.modal.id = 'action-bar-modal';
316
- await document.body.appendChild(this.modal);
314
+ modalOnDom.id = 'action-bar-modal';
315
+ return modalOnDom;
317
316
  }
318
317
 
319
318
  /**
@@ -321,7 +320,9 @@ export default class IABookActions extends LitElement {
321
320
  */
322
321
  async showWarningModal() {
323
322
  console.log('****** showWarningModal ******');
324
- await this.useModalManager();
323
+ // clear modal
324
+ this.modal?.showModal(new ModalConfig({ customModalContent: nothing }));
325
+ this.modal?.closeModal();
325
326
 
326
327
  // if secondsLeft < 60, consider it 1 minute
327
328
  let { secondsLeft } = this.loanRenewResult;
@@ -331,23 +332,21 @@ export default class IABookActions extends LitElement {
331
332
  secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
332
333
  }
333
334
 
334
- const config = new ModalConfig();
335
- config.headline = 'Are you still here?';
336
- config.showCloseButton = false;
337
- config.closeOnBackdropClick = false;
338
- config.message = this.loanRenewHelper?.getMessageTexts(
339
- this.loanRenewResult.texts,
340
- secondsLeft
341
- );
335
+ const config = new ModalConfig({
336
+ headline: 'Are you still here?',
337
+ showCloseButton: false,
338
+ closeOnBackdropClick: false,
339
+ message: this.loanRenewHelper?.getMessageTexts(
340
+ this.loanRenewResult.texts,
341
+ secondsLeft
342
+ )
343
+ });
342
344
 
343
- const customContent = html`<br />
344
- <div id="custom-buttons" style="display:flex;justify-content:center;">
345
+ const customModalContent = html`<br />
346
+ <div id="book-action-bar-custom-buttons" style="display:flex;justify-content:center;">
345
347
  <button
346
348
  style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
347
- @click=${async event => {
348
- await this.changeModalState(event);
349
- this.loanRenewResult = { texts: '', renewNow: true };
350
- }}
349
+ @click=${event => this.patronWantsToRenewBook(event)}
351
350
  >
352
351
  Keep reading
353
352
  </button>
@@ -363,7 +362,12 @@ export default class IABookActions extends LitElement {
363
362
  </button>
364
363
  </div> `;
365
364
 
366
- this.modal?.showModal({ config, customModalContent: customContent });
365
+ this.modal?.showModal({ config, customModalContent });
366
+ }
367
+
368
+ async patronWantsToRenewBook(event) {
369
+ this.changeModalState(event);
370
+ this.loanRenewResult = { texts: '', renewNow: true };
367
371
  }
368
372
 
369
373
  /**
@@ -374,9 +378,11 @@ export default class IABookActions extends LitElement {
374
378
  * @param {Event} event
375
379
  */
376
380
  changeModalState(event) {
381
+ // this doesn't really work? shows empty button
377
382
  if (event.target === undefined) return;
378
383
 
379
384
  const button = event.target;
385
+ button.disabled = true;
380
386
  button.innerHTML = `<ia-activity-indicator
381
387
  mode="processing"
382
388
  style=${modalButtonStyle.loaderIcon}
@@ -392,15 +398,15 @@ export default class IABookActions extends LitElement {
392
398
  */
393
399
  async showExpiredModal() {
394
400
  console.log('showExpiredModal()');
395
- await this.useModalManager();
396
401
 
397
- const config = new ModalConfig();
398
- config.headline = '';
399
- config.showCloseButton = false;
400
- config.closeOnBackdropClick = false;
401
- config.message = 'This book has been returned due to inactivity.';
402
+ const config = new ModalConfig({
403
+ headline: '',
404
+ showCloseButton: false,
405
+ closeOnBackdropClick: false,
406
+ message: 'This book has been returned due to inactivity.'
407
+ });
402
408
 
403
- const customContent = html`<br />
409
+ const customModalContent = html`<br />
404
410
  <div style="text-align: center">
405
411
  <button
406
412
  style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
@@ -412,15 +418,7 @@ export default class IABookActions extends LitElement {
412
418
  </button>
413
419
  </div> `;
414
420
 
415
- this.modal?.showModal({ config, customModalContent: customContent });
416
- }
417
-
418
- /**
419
- * close/hide modal-manager
420
- */
421
- async closeModalManager() {
422
- this.modal = document.querySelector('modal-manager');
423
- this.modal?.closeModal();
421
+ this.modal?.showModal({ config, customModalContent });
424
422
  }
425
423
 
426
424
  /**
@@ -478,21 +476,6 @@ export default class IABookActions extends LitElement {
478
476
  });
479
477
  }
480
478
 
481
- async browseHasRenew() {
482
- window?.IALendingIntervals?.clearAll();
483
-
484
- const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
485
- const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
486
-
487
- const currStatus = {
488
- ...this.lendingStatus,
489
- user_has_browsed: true,
490
- browsingExpired: false,
491
- secondsLeftOnLoan: secondsLeft,
492
- };
493
- this.lendingStatus = currStatus;
494
- }
495
-
496
479
  /**
497
480
  * Execute when loan is expired
498
481
  */
@@ -518,7 +501,11 @@ export default class IABookActions extends LitElement {
518
501
 
519
502
  async startBrowseTimer() {
520
503
  clearTimeout(this.browseTimer);
521
- console.log('startBrowseTimerstartBrowseTimer just cleared timer', this.browseTimer, this.lendingStatus);
504
+ console.log(
505
+ 'startBrowseTimerstartBrowseTimer just cleared timer',
506
+ this.browseTimer,
507
+ this.lendingStatus
508
+ );
522
509
 
523
510
  const {
524
511
  browsingExpired,
@@ -531,7 +518,10 @@ export default class IABookActions extends LitElement {
531
518
  }
532
519
 
533
520
  this.browseTimer = setTimeout(() => {
534
- console.log('start `this.browseTimer will fire his.browseHasExpired() - secondsLeftOnLoan', secondsLeftOnLoan);
521
+ console.log(
522
+ 'start `this.browseTimer will fire his.browseHasExpired() - secondsLeftOnLoan',
523
+ secondsLeftOnLoan
524
+ );
535
525
  this.browseHasExpired();
536
526
  }, secondsLeftOnLoan * 1000);
537
527
  }
@@ -543,11 +533,22 @@ export default class IABookActions extends LitElement {
543
533
  const timerCountdown = this._shadowRoot.querySelector('timer-countdown');
544
534
  if (!timerCountdown) return;
545
535
 
546
- const secondsLeft = Number(this.lendingStatus.secondsLeftOnLoan);
547
- const strokeDashOffset =
548
- (secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315;
536
+ const secondsLeft = Number.parseInt(
537
+ Number(this.lendingStatus.secondsLeftOnLoan),
538
+ 10
539
+ );
540
+ const firstStrokeDashOffset = Number.parseInt(
541
+ (secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315 * 1.5,
542
+ 10
543
+ );
544
+ const actualStrokeDashOffset =
545
+ firstStrokeDashOffset > 315 ? 315 : firstStrokeDashOffset;
549
546
 
550
- console.log('resetTimerCountState === ', secondsLeft);
547
+ console.log('resetTimerCountState === ', {
548
+ secondsLeft,
549
+ firstStrokeDashOffset,
550
+ actualStrokeDashOffset,
551
+ });
551
552
 
552
553
  // set seconds left in loan expire
553
554
  timerCountdown.style?.setProperty('--secondsLeftOnLoan', `${secondsLeft}s`);
@@ -555,7 +556,7 @@ export default class IABookActions extends LitElement {
555
556
  // set circle stroke offset left in loan expire
556
557
  timerCountdown.style?.setProperty(
557
558
  '--strokeLeftOnLoan',
558
- `${Number(strokeDashOffset)}` // the perimeter of the circle = (π * 2 * radius)
559
+ `${actualStrokeDashOffset}` // the perimeter of the circle = (π * 2 * radius)
559
560
  );
560
561
 
561
562
  const animationCircle = timerCountdown.shadowRoot.querySelector('.circle');
@@ -584,14 +585,6 @@ export default class IABookActions extends LitElement {
584
585
  ></book-title-bar>`;
585
586
  }
586
587
 
587
- get timerCountdownTemplate() {
588
- return this.borrowType === 'browsed'
589
- ? html`<timer-countdown
590
- .secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
591
- ></timer-countdown>`
592
- : nothing;
593
- }
594
-
595
588
  get bookActionBar() {
596
589
  return html`
597
590
  <collapsible-action-group
@@ -616,7 +609,10 @@ export default class IABookActions extends LitElement {
616
609
  >
617
610
  </collapsible-action-group>
618
611
  ${this.textGroupTemplate} ${this.infoIconTemplate}
619
- ${this.timerCountdownTemplate}
612
+ <timer-countdown
613
+ .secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
614
+ class=${this.borrowType === 'browsed' ? '' : 'hide'}
615
+ ></timer-countdown>
620
616
  `;
621
617
  }
622
618
 
@@ -635,13 +631,24 @@ export default class IABookActions extends LitElement {
635
631
  console.log('IABookActions: AutoRenewed:- ', {
636
632
  ajaxResponse: event?.detail?.data,
637
633
  loanRenewResult: this.loanRenewResult,
638
- secondsLeftOnLoan: Math.round(this.lendingStatus.secondsLeftOnLoan),
634
+ secondsLeftOnLoan: Math.round(this.lendingStatus.secondsLeftOnLoan), // stale? how to fix
639
635
  });
640
636
 
641
- /**
642
- * update the lendingStatus property
643
- */
644
- await this.browseHasRenew();
637
+ // Now, let's reset loan duration & this.lendingStatus
638
+ const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
639
+ const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
640
+
641
+ const currStatus = {
642
+ ...this.lendingStatus,
643
+ user_has_browsed: true,
644
+ browsingExpired: false,
645
+ secondsLeftOnLoan: secondsLeft,
646
+ };
647
+ this.lendingStatus = currStatus;
648
+
649
+ console.log('~~~ handleLoanAutoRenewed - new this.lendingStatus', {
650
+ secondsLeftOnLoan: this.lendingStatus.secondsLeftOnLoan,
651
+ });
645
652
 
646
653
  /**
647
654
  * reset timer countdown states
@@ -649,8 +656,12 @@ export default class IABookActions extends LitElement {
649
656
  await this.resetTimerCountState();
650
657
 
651
658
  // close the modal
652
- this.modal?.remove();
653
- this.modal?.showModal({ config: {}, customModalContent: `` });
659
+ this.modal.removeAttribute('id');
660
+ const editedActionButtons = this.modal.shadowRoot.querySelector('#book-action-bar-custom-buttons');
661
+ if (editedActionButtons) {
662
+ editedActionButtons.parentElement.removeChild(editedActionButtons);
663
+ }
664
+ this.modal?.closeModal();
654
665
 
655
666
  window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
656
667
  }
@@ -673,9 +684,14 @@ export default class IABookActions extends LitElement {
673
684
  secondsLeft = Math.round(secondsLeft); // round number
674
685
 
675
686
  // re-sync timer if gone off because of background window
687
+ // side effect: updates this.lendingStatus & kicks off lifecycle,
688
+ // if really updated, escape from here
676
689
  const resync = await this.reSyncTimerIfGoneOff(secondsLeft);
677
690
 
678
- console.log("*** startTimerCountdown ***", secondsLeft, resync);
691
+ console.log('*** startTimerCountdown = reSyncTimerIfGoneOff ***', {
692
+ secondsLeft,
693
+ resync,
694
+ });
679
695
 
680
696
  if (resync) {
681
697
  console.log('have resyncd, will end startTimerCountdown here - ');
@@ -883,7 +899,6 @@ export default class IABookActions extends LitElement {
883
899
 
884
900
  /* show error message if something went wrong */
885
901
  async showErrorModal(errorMsg, action) {
886
- await this.useModalManager();
887
902
 
888
903
  const modalConfig = new ModalConfig({
889
904
  title: 'Lending error',
@@ -948,6 +963,10 @@ export default class IABookActions extends LitElement {
948
963
  display: block;
949
964
  }
950
965
 
966
+ .hide {
967
+ display: none;
968
+ }
969
+
951
970
  .lending-wrapper {
952
971
  width: 100%;
953
972
  margin: 0 auto;