@internetarchive/ia-book-actions 1.0.0 → 1.1.0-alpha10

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: 65, loanRenewAtLast: 60, pageChangedInLast: 15 };
134
+ let loanTotalTime2Min = { loanTotalTime: 170, loanRenewAtLast: 80, pageChangedInLast: 15 };
135
135
  let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 180, pageChangedInLast: 15 };
136
136
  let loanTotalTime1Hour = { loanTotalTime: 3600, loanRenewAtLast: 660, pageChangedInLast: 900 };
137
137
 
@@ -150,6 +150,25 @@
150
150
  });
151
151
  });
152
152
 
153
+ document.querySelectorAll('.searchParam input[type=checkbox]').forEach((item) => {
154
+ item.addEventListener('click', (e) => {
155
+ var searchParams = new URLSearchParams(window.location.search);
156
+ var separate = '';
157
+ if (e.target.checked) {
158
+ separate = '?';
159
+ searchParams.set('q', 'test');
160
+ } else {
161
+ separate = '';
162
+ searchParams.delete('q');
163
+ }
164
+
165
+ if (history.pushState) {
166
+ var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + separate + searchParams;
167
+ window.history.pushState({path:newurl},'',newurl);
168
+ }
169
+ });
170
+ });
171
+
153
172
  document.querySelectorAll('.errorEnable input[type=checkbox]').forEach((item) => {
154
173
  if (window.location.href.indexOf('?error=true') !== -1) {
155
174
  item.checked = true;
@@ -327,7 +346,6 @@
327
346
  // listen for IABookReader:BrowsingHasExpired
328
347
  window.addEventListener('IABookReader:BrowsingHasExpired', () => {
329
348
  console.log('IABookReader:BrowsingHasExpired EVENT FIRED');
330
- alert('IABookReader:BrowsingHasExpired EVENT FIRED');
331
349
  });
332
350
  </script>
333
351
 
@@ -339,6 +357,8 @@
339
357
  <td class="titleBar">
340
358
  <label><input type="checkbox" name="title" value="title" />Title Bar</label>
341
359
  </td>
360
+ <td class="searchParam">
361
+ <label><input type="checkbox" name="search" value="Search Param" />Search Param</label>
342
362
  <td>
343
363
  <button class="pageChangedEvent">Page Change Event</button>
344
364
  </td>
@@ -370,7 +390,6 @@
370
390
  </div>
371
391
  <div>
372
392
  <button id="show_expired_modal">While Browsing (`user_has_browsed`), Expire book & show its modal</button>
373
- how_expired_modal
374
393
  </div>
375
394
  </td>
376
395
  <td class="availableToBorrow">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "1.0.0",
3
+ "version": "1.1.0-alpha10",
4
4
  "description": "Bookreader actions for borrowable book",
5
5
  "author": "Internet Archive",
6
6
  "license": "AGPL-3.0-only",
@@ -14,16 +14,16 @@
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 --playwright --browsers chromium firefox webkit",
18
- "test:watch": "web-test-runner --watch --playwright --browsers chromium firefox webkit"
17
+ "test:fast": "web-test-runner --coverage",
18
+ "test:watch": "web-test-runner --watch"
19
19
  },
20
20
  "dependencies": {
21
21
  "@internetarchive/icon-info": "^1.2.6",
22
22
  "@internetarchive/local-cache": "^0.2.1",
23
- "@internetarchive/modal-manager": "^0.2.12",
23
+ "@internetarchive/modal-manager": "2.0.0",
24
24
  "@internetarchive/shared-resize-observer": "^0.2.0",
25
- "@internetarchive/toast-manager": "0.1.0",
26
- "lit": "^2.5.0"
25
+ "install-deps": "^1.1.0",
26
+ "lit": "^2.8.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@open-wc/eslint-config": "^4.2.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: 155,
121
+ secondsLeftOnLoan: 170,
122
122
  shouldProtectImages: true,
123
123
  totalWaitlistCount: 0,
124
124
  userHasBorrowed: false,
@@ -21,6 +21,7 @@ export default css`
21
21
  .action-buttons .ia-button {
22
22
  margin: 0;
23
23
  height: 3.5rem;
24
+ padding: 0 2rem;
24
25
  }
25
26
  .action-buttons .desktop {
26
27
  background-color: ${whiteColor};
@@ -36,7 +36,7 @@ export default css`
36
36
  align-items: center;
37
37
  transition: all 0.1s ease 0s;
38
38
  vertical-align: middle;
39
- padding: 0 3rem;
39
+ padding: 0 1rem;
40
40
  outline-color: ${whiteColor};
41
41
  outline-offset: -4px;
42
42
  user-select: none;
@@ -178,7 +178,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
178
178
  get renderSecondaryActions() {
179
179
  if (!this.secondaryActions.length) return nothing;
180
180
 
181
- return this.secondaryActions.map(action => this.renderActionLink(action));
181
+ return this.secondaryActions.map(action => this.renderActionButton(action));
182
182
  }
183
183
 
184
184
  /**
@@ -47,7 +47,7 @@ export default class TimerCountdown extends LitElement {
47
47
  }
48
48
 
49
49
  render() {
50
- const viewClass = this.displayTime ? 'view' : 'hide';
50
+ const viewClass = this.displayTime ? 'view' : 'hide1';
51
51
  return html`
52
52
  <button
53
53
  id="timer-counter"
@@ -207,8 +207,6 @@ export default class ActionsConfig {
207
207
  id: 'adminAccess',
208
208
  text: 'Admin Access',
209
209
  title: 'You have administrative privileges to read this book',
210
- url: '?admin=1',
211
- target: '_self',
212
210
  className: 'danger',
213
211
  analyticsEvent: {
214
212
  category: this.analyticsCategories.adminAccess,
@@ -115,6 +115,11 @@ export default class ActionsHandler extends LitElement {
115
115
  this.addEventListener('adminAccess', ({ detail }) => {
116
116
  const { category, action } = detail.event;
117
117
  this.loanAnanlytics?.sendEvent(category, action, this.identifier);
118
+
119
+ // keep existing params and add new one
120
+ const url = new URL(window.location.href);
121
+ url.searchParams.append('admin', 1);
122
+ window.location.search = url.search;
118
123
  });
119
124
 
120
125
  this.addEventListener('exitAdminAccess', ({ detail }) => {
@@ -4,7 +4,6 @@ import { html, css, LitElement, nothing } from 'lit';
4
4
 
5
5
  import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
6
6
  import { ModalConfig } from '@internetarchive/modal-manager';
7
- import { ToastConfig } from '@internetarchive/toast-manager';
8
7
  import { LocalCache } from '@internetarchive/local-cache';
9
8
 
10
9
  import './components/collapsible-action-group.js';
@@ -283,6 +282,25 @@ export default class IABookActions extends LitElement {
283
282
  this.autoLoanRenewChecker(true);
284
283
  }
285
284
  });
285
+
286
+ /**
287
+ * auto-renew interval may stale when tab is in background,
288
+ * so [visibilitychange] event can trigger timer to show relavent messages
289
+ */
290
+ document.addEventListener("visibilitychange", async () => {
291
+ if (!document.hidden) {
292
+ log('visibilitychange', new Date().getMinutes, new Date().getSeconds());
293
+
294
+ const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
295
+ const secondsLeft = Math.round((loanTime - new Date()) / 1000); // different in seconds
296
+
297
+ if (secondsLeft >= this.timerExecutionSeconds) {
298
+ this.setIntervalExecutionBlock(Number(secondsLeft));
299
+ } else {
300
+ this.disconnectedCallback();
301
+ }
302
+ }
303
+ });
286
304
  }
287
305
 
288
306
  /**
@@ -487,36 +505,6 @@ export default class IABookActions extends LitElement {
487
505
  this.toast?.remove();
488
506
  }
489
507
 
490
- /**
491
- * @deprecated
492
- * Show toast messages on some specific loan renew features. e.g.
493
- * - show message when book is auto renewed
494
- * - show message when book is expired
495
- * - show message having remaining time when book is about to auto returned
496
- */
497
- async showToastMessage() {
498
- await this.useToastManager();
499
-
500
- // if secondsLeft < 60, consider it 1 minute
501
- let { secondsLeft } = this.loanRenewResult;
502
- if (secondsLeft === undefined) {
503
- secondsLeft = this.lendingStatus.secondsLeftOnLoan;
504
- } else {
505
- secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
506
- }
507
-
508
- const config = new ToastConfig();
509
- config.dismisOnClick = true;
510
- config.texts = this.loanRenewHelper?.getMessageTexts(
511
- this.loanRenewResult.texts,
512
- secondsLeft
513
- );
514
-
515
- this.toast?.showToast({
516
- config,
517
- });
518
- }
519
-
520
508
  /**
521
509
  * Execute when loan is expired
522
510
  */
@@ -677,47 +665,62 @@ export default class IABookActions extends LitElement {
677
665
  startTimerCountdown() {
678
666
  window?.IALendingIntervals?.clearTimerCountdown();
679
667
 
680
- let secondsLeft = Number(this.lendingStatus.secondsLeftOnLoan);
668
+ const secondsLeft = Number(this.lendingStatus.secondsLeftOnLoan);
681
669
  this.timeWhenTimerStart = new Date();
682
670
 
683
671
  window.IALendingIntervals.timerCountdown = setInterval(async () => {
684
- secondsLeft -= this.timerExecutionSeconds;
685
- secondsLeft = Math.round(secondsLeft); // round number
686
-
687
- // re-sync timer if gone off because of background window
688
- // side effect: updates this.lendingStatus & kicks off lifecycle,
689
- // if really updated, escape from here
690
- const resync = await this.reSyncTimerIfGoneOff(secondsLeft);
691
-
692
- if (resync) {
693
- log('startTimerCountdown --- stale, timer has resyncd', {
694
- secondsLeft,
695
- });
696
- return;
697
- }
672
+ // interval execution block
673
+ await this.setIntervalExecutionBlock(secondsLeft);
674
+ }, this.timerExecutionSeconds * 1000);
675
+ }
698
676
 
699
- log('startTimerCountdown --- countdown still valid. continue...', {
700
- resync,
677
+ /**
678
+ * setInterval execution function do following things
679
+ * - if setInterval timer gone off, let's resync
680
+ * - loan-renew attempt to renew the loan OR show relavant message
681
+ * - if loan has expired, clear interval timers
682
+ *
683
+ * @param {Number} secondsLeftOnLoan
684
+ */
685
+ async setIntervalExecutionBlock(secondsLeftOnLoan) {
686
+ let secondsLeft = secondsLeftOnLoan;
687
+ secondsLeft -= this.timerExecutionSeconds;
688
+ secondsLeft = Math.round(secondsLeft); // round number
689
+
690
+ // re-sync timer if gone off because of background window
691
+ // side effect: updates this.lendingStatus & kicks off lifecycle,
692
+ // if really updated, escape from here
693
+ const resyncd = await this.reSyncTimerIfGoneOff(secondsLeft);
694
+
695
+ if (resyncd?.hasSynced) {
696
+ secondsLeft = resyncd.whatShouldLeft;
697
+
698
+ log('startTimerCountdown --- stale, timer has resyncd', {
701
699
  secondsLeft,
702
- loanRenewAtLast: this.loanRenewTimeConfig.loanRenewAtLast,
703
700
  });
701
+ }
704
702
 
705
- /**
706
- * execute from last 10th minute to 0th minute
707
- * - 10th - to check if user has viewed
708
- * - till 0th - to show warning msg with remaining time to auto expired
709
- * @see IABookActions::bindLoanRenewEvents
710
- */
711
- if (secondsLeft <= this.loanRenewTimeConfig.loanRenewAtLast) {
712
- await this.loanRenewAttempt(secondsLeft);
713
- }
703
+ log('startTimerCountdown --- countdown still valid. continue...', {
704
+ resyncd,
705
+ secondsLeft,
706
+ loanRenewAtLast: this.loanRenewTimeConfig.loanRenewAtLast,
707
+ }, new Date().getMinutes(), new Date().getSeconds());
714
708
 
715
- // clear interval in secondsLeft if less
716
- if (secondsLeft <= this.timerExecutionSeconds) {
717
- this.disconnectedCallback();
718
- window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
719
- }
720
- }, this.timerExecutionSeconds * 1000);
709
+ /**
710
+ * execute from last 10th minute to 0th minute
711
+ * - 10th - to check if user has viewed
712
+ * - till 0th - to show warning msg with remaining time to auto expired
713
+ * @see IABookActions::bindLoanRenewEvents
714
+ */
715
+ if (secondsLeft <= this.loanRenewTimeConfig.loanRenewAtLast) {
716
+ await this.loanRenewAttempt(secondsLeft);
717
+ }
718
+
719
+ // clear interval in secondsLeft if less
720
+ if (secondsLeft <= this.timerExecutionSeconds) {
721
+ this.disconnectedCallback();
722
+ window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
723
+ }
721
724
  }
722
725
 
723
726
  /**
@@ -761,7 +764,7 @@ export default class IABookActions extends LitElement {
761
764
  if (whatIsleft !== whatShouldLeft) {
762
765
  log(`reSyncTimerIfGoneOff --- let's re-sync.`);
763
766
 
764
- return true;
767
+ return { hasSynced: true, whatShouldLeft };
765
768
  }
766
769
  return false;
767
770
  }
@@ -421,7 +421,7 @@ describe('Auto renew one hour loan', () => {
421
421
  // timer-countdown reflects decreased loan time
422
422
  expect(el.timerCountdownEl.secondsLeftOnLoan).to.equal(8);
423
423
 
424
- expect(el.postInitComplete).to.equal(33);
424
+ expect(el.postInitComplete).to.equal(false);
425
425
 
426
426
  // dispatch loanAutoRenewed event - test 200 callback
427
427
  const collapsibleActionGroupEl = el.shadowRoot.querySelector(
@@ -445,7 +445,7 @@ describe('Auto renew one hour loan', () => {
445
445
  expect(el.loanRenewResult.renewNow).to.equal(true);
446
446
  expect(el.loanRenewResult.secondsLeft).to.equal(10);
447
447
  expect(el.timerCountdownEl).to.exist;
448
- expect(el.timerCountdownEl.secondsLeftOnLoan).to.equal(loanTime);
448
+ expect(el.timerCountdownEl.secondsLeftOnLoan).to.equal(8);
449
449
  });
450
450
  });
451
451