@internetarchive/ia-book-actions 0.0.29-alpha35 → 0.0.29-alpha37

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
@@ -72,6 +72,10 @@
72
72
  margin: 2px;
73
73
  }
74
74
 
75
+ fieldset {
76
+ display: inline-grid;
77
+ }
78
+
75
79
  body.modal-manager-open {
76
80
  overflow: hidden;
77
81
  }
@@ -129,10 +133,10 @@
129
133
 
130
134
  let isDevBox = true;
131
135
  iaBookActions.loanRenewConfig = {
132
- totalTime: isDevBox ? 120 : 3600, // 60 second = 1 min
133
- autoCheckAt: isDevBox ? 115 : 3540, // at last 10th minute
134
- pageChangedInLast: isDevBox ? 80 : 900, // within last 15 second/minute
135
- env: isDevBox ? 'dev' : 'prod',
136
+ totalTime: isDevBox ? 13 : 3600, // 60 second = 1 min
137
+ autoCheckAt: isDevBox ? 10 : 3540, // at last 10th minute
138
+ pageChangedInLast: isDevBox ? 5 : 900, // within last 15 second/minute
139
+ isDevBox: isDevBox,
136
140
  };
137
141
 
138
142
  let lendingStatus1 = iaBookActions.lendingStatus;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "0.0.29-alpha35",
3
+ "version": "0.0.29-alpha37",
4
4
  "description": "Bookreader actions for borrowable book",
5
5
  "author": "Internet Archive",
6
6
  "license": "AGPL-3.0-only",
@@ -100,7 +100,7 @@ export const canBrowseAndBorrow = {
100
100
  // userid: "",
101
101
  bookUrl: '/details/practicalorganic00plim',
102
102
  daysLeftOnLoan: 0,
103
- isAdmin: false,
103
+ isAdmin: true,
104
104
  isArchiveOrgLending: true,
105
105
  isAvailable: false,
106
106
  isAvailableForBrowsing: false,
@@ -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: 12,
121
+ secondsLeftOnLoan: 3591,
122
122
  shouldProtectImages: true,
123
123
  totalWaitlistCount: 0,
124
124
  userHasBorrowed: false,
@@ -1,4 +1,5 @@
1
1
  import { html, css, LitElement } from 'lit';
2
+ import { sentryLogs } from '../core/config/sentry-events.js';
2
3
 
3
4
  export default class TimerCountdown extends LitElement {
4
5
  static get properties() {
@@ -32,32 +33,33 @@ export default class TimerCountdown extends LitElement {
32
33
  // execute interval in each second in-case of dev environment
33
34
  this.timerInterval = setInterval(
34
35
  () => {
35
- this.timeLeftOnLoan -= this.loanRenewConfig.env === 'dev' ? 1 : 60;
36
+ this.timeLeftOnLoan -= this.loanRenewConfig.isDevBox ? 1 : 60;
37
+ const timeLeft = Math.round(this.timeLeftOnLoan);
36
38
 
37
39
  // execute from last 10th minute to 0th minute
38
40
  // - 10th - to check if user has viewed
39
41
  // - till 0th - to show warning msg with remaining time to auto returned
40
- if (
41
- Math.round(this.timeLeftOnLoan) <= this.loanRenewConfig.autoCheckAt
42
- ) {
42
+ if (timeLeft <= this.loanRenewConfig.autoCheckAt) {
43
43
  this.dispatchEvent(
44
44
  new CustomEvent('IABookActions:loanRenew', {
45
45
  detail: {
46
46
  hasPageChanged: false,
47
- timeLeft: Math.round(this.timeLeftOnLoan),
47
+ timeLeft,
48
48
  },
49
49
  bubbles: true,
50
50
  composed: true,
51
51
  })
52
52
  );
53
53
  }
54
- console.log(this.timeLeftOnLoan, this.loanRenewConfig.autoCheckAt)
55
- // clear interval if timer is < this.loanRenewConfig.autoCheckAt
56
- if (this.timeLeftOnLoan < this.loanRenewConfig.autoCheckAt) {
54
+
55
+ // clear interval
56
+ if (timeLeft <= 1) {
57
57
  clearInterval(this.timerInterval);
58
+ window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
59
+ console.log(sentryLogs.clearOneHourTimer);
58
60
  }
59
61
  },
60
- this.loanRenewConfig.env === 'dev' ? 1000 : 60000
62
+ this.loanRenewConfig.isDevBox ? 1000 : 60000
61
63
  );
62
64
  }
63
65
 
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Analytics categories and events. Used when building actions in
3
+ */
4
+ export const sentryLogs = {
5
+ disconnectedCallback: 'IABookActions:disconnectedCallback',
6
+ bookHasRenewed:
7
+ 'IABookActions:handleLoanAutoRenewed - book has renewed for next one hour',
8
+ browseHasExpired:
9
+ 'IABookActions:browseHasExpired - one-hour loan has been expired',
10
+ bookWasExpired:
11
+ 'IABookActions:setupLendingToolbarActions - book was expired at intial, no tokenPoller',
12
+ clearTokenPoller:
13
+ 'IABookActions:startLoanTokenPoller - clearing token poller interval',
14
+ clearOneHourTimer:
15
+ 'IABookActions:timerCountdown - one-hour timer interval cleared',
16
+ enableBookAccess: 'IABookActions:enableBookAccess',
17
+ handleLoanTokenPoller: 'IABookActions:handleLoanTokenPoller',
18
+ setConsecutiveLoanCounts: 'IABookActions:setConsecutiveLoanCounts',
19
+ actionsHandlerService: 'IABookActions:actionsHandlerService',
20
+ };
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable */
2
+ import { sentryLogs } from '../../config/sentry-events.js';
2
3
 
3
4
  /**
4
5
  * Helper to call loan service
@@ -64,7 +65,9 @@ export default async function ActionsHandlerService(options) {
64
65
  option?.error(data);
65
66
  }
66
67
  });
67
- } catch (err) {
68
- window?.Sentry?.captureException(err);
68
+ } catch (error) {
69
+ window?.Sentry?.captureException(
70
+ `${sentryLogs.actionsHandlerService} - Error: ${error}`
71
+ );
69
72
  }
70
73
  }
@@ -1,6 +1,8 @@
1
1
  import { LitElement } from 'lit';
2
2
 
3
3
  import { URLHelper } from '../../config/url-helper.js';
4
+ import { sentryLogs } from '../../config/sentry-events.js';
5
+
4
6
  import ActionsHandlerService from './actions-handler-service.js';
5
7
  import * as Cookies from '../doc-cookies.js';
6
8
 
@@ -103,12 +105,12 @@ export default class ActionsHandler extends LitElement {
103
105
  handleBrowseIt() {
104
106
  const action = 'browse_book';
105
107
  this.dispatchToggleActionGroup();
106
- this.setBrowseTimeSession();
107
108
 
108
109
  ActionsHandlerService({
109
110
  action,
110
111
  identifier: this.identifier,
111
112
  success: () => {
113
+ this.setBrowseTimeSession();
112
114
  this.handleReadItNow();
113
115
  },
114
116
  error: data => {
@@ -283,7 +285,9 @@ export default class ActionsHandler extends LitElement {
283
285
  // set new value
284
286
  Cookies.setItem(storageKey, newCount, date, '/');
285
287
  } catch (error) {
286
- window?.Sentry?.captureException(error);
288
+ window?.Sentry?.captureException(
289
+ `${sentryLogs.setConsecutiveLoanCounts} - Error: ${error}`
290
+ );
287
291
  this.sendEvent('Cookies-Error-Actions', error);
288
292
  }
289
293
  }
@@ -27,7 +27,7 @@ export class LoanRenewHelper {
27
27
  if (this.hasPageChanged) {
28
28
  return this.pageChanged(); // user clicked on page
29
29
  }
30
- return this.autoChecker(); // auto checker at 50th minute
30
+ return this.autoChecker(); // auto checker at last 10th minute
31
31
  } catch (error) {
32
32
  console.log(error);
33
33
  }
@@ -57,7 +57,7 @@ export class LoanRenewHelper {
57
57
  );
58
58
 
59
59
  // if user viewed new page in last 10 minutes, renew immediately
60
- if (currentTime >= lastTimeFrame) {
60
+ if (lastTimeFrame !== null && currentTime >= lastTimeFrame) {
61
61
  this.result.texts = this.loanRenewMessage;
62
62
  this.result.renewNow = true;
63
63
  console.log('manually renewed by page click!');
@@ -68,33 +68,31 @@ export class LoanRenewHelper {
68
68
  }
69
69
 
70
70
  /**
71
- * Trigger this function when countdown hits last 10 minutes
72
- * - if user is open new page, just renew the loan at last 10th minute
71
+ * Trigger this function when countdown hits at last 10th minute
72
+ * - if user is active, just renew the loan at last 10th minute
73
73
  *
74
74
  * @returns {this.result}
75
75
  */
76
76
  async autoChecker() {
77
- const currentTime = new Date();
78
77
  const { pageChangedInLast } = this.loanRenewConfig;
79
- const lastPageFlipTime = await this.localCache.get(
78
+ const pageChangedTime = await this.localCache.get(
80
79
  `${this.identifier}-pageChangedTime`
81
80
  );
82
81
 
83
- // last 15 min if used flipped a page.
84
- const lastFlipTimeFrame = this.changeTime(
85
- currentTime,
82
+ // in last 15 min if user make any activity.
83
+ const pageChangeTimeFrame = this.changeTime(
84
+ new Date(),
86
85
  pageChangedInLast,
87
86
  'sub'
88
87
  ); // 15 seconds
89
88
 
90
89
  if (
91
- lastPageFlipTime === undefined ||
92
- lastPageFlipTime <= lastFlipTimeFrame
90
+ pageChangedTime === undefined ||
91
+ pageChangedTime <= pageChangeTimeFrame
93
92
  ) {
94
93
  this.result.texts = this.loanReturnWarning;
95
94
  this.result.renewNow = false; // not viewed
96
- // console.log('not viewed!');
97
- } else if (lastPageFlipTime >= lastFlipTimeFrame) {
95
+ } else if (pageChangedTime >= pageChangeTimeFrame) {
98
96
  this.result.texts = '';
99
97
  this.result.renewNow = true; // viewed in last time frame
100
98
  console.log('silently renewed!');
@@ -1,4 +1,6 @@
1
1
  import ActionsHandlerService from './actions-handler/actions-handler-service.js';
2
+ import { sentryLogs } from '../config/sentry-events.js';
3
+
2
4
  import * as Cookies from './doc-cookies.js';
3
5
 
4
6
  /**
@@ -43,7 +45,9 @@ export class LoanTokenPoller {
43
45
  );
44
46
  consecutiveLoanCounts = existingCount ?? 1;
45
47
  } catch (error) {
46
- window?.Sentry?.captureException(error);
48
+ window?.Sentry?.captureException(
49
+ `${sentryLogs.enableBookAcces} - CookieError: ${error}`
50
+ );
47
51
  this.sendEvent('Cookies-Error-Token', error);
48
52
  }
49
53
  }
@@ -68,7 +72,10 @@ export class LoanTokenPoller {
68
72
 
69
73
  this.sendEvent(category, action);
70
74
  } else {
71
- window?.Sentry?.captureMessage('enableBookAccess error');
75
+ window?.Sentry?.captureMessage(
76
+ `${sentryLogs.enableBookAccess} - not borrowed`
77
+ );
78
+
72
79
  // if book is not browsed, just clear token polling interval
73
80
  this.disconnectedInterval(); // stop token fetch api
74
81
  }
@@ -88,12 +95,14 @@ export class LoanTokenPoller {
88
95
  identifier: this.identifier,
89
96
  action,
90
97
  error: data => {
91
- window?.Sentry?.captureMessage(
92
- 'handleLoanTokenPoller error',
93
- JSON.stringify(data)
94
- );
95
98
  this.disconnectedInterval(); // stop token fetch api
96
99
  this.errorCallback({ detail: { action, data } });
100
+
101
+ // send error to Sentry
102
+ window?.Sentry?.captureMessage(
103
+ `${sentryLogs.handleLoanTokenPoller} - Error: ${JSON.stringify(data)}`
104
+ );
105
+
97
106
  // send LendingServiceError to GA
98
107
  this.sendEvent('LendingServiceLoanError', action);
99
108
  },
@@ -14,6 +14,7 @@ import './components/timer-countdown.js';
14
14
 
15
15
  import { GetLendingActions } from './core/services/get-lending-actions.js';
16
16
  import { mobileContainerWidth } from './core/config/constants.js';
17
+ import { sentryLogs } from './core/config/sentry-events.js';
17
18
  import { LoanTokenPoller } from './core/services/loan-token-poller.js';
18
19
  import { LoanRenewHelper } from './core/services/loan-renew-helper.js';
19
20
 
@@ -92,7 +93,7 @@ export default class IABookActions extends LitElement {
92
93
 
93
94
  disconnectedCallback() {
94
95
  this.tokenPoller.disconnectedInterval();
95
- window?.Sentry?.captureMessage('disconnectedCallback');
96
+ window?.Sentry?.captureMessage(sentryLogs.disconnectedCallback);
96
97
  this.disconnectResizeObserver();
97
98
  }
98
99
 
@@ -184,9 +185,7 @@ export default class IABookActions extends LitElement {
184
185
  this.lendingStatus?.browsingExpired;
185
186
  if (hasExpired) {
186
187
  if (!this.tokenPoller) {
187
- window?.Sentry?.captureMessage(
188
- 'setupLendingToolbarActions hasExpired - no tokenPoller'
189
- );
188
+ window?.Sentry?.captureMessage(sentryLogs.bookWasExpired);
190
189
  }
191
190
  this.tokenPoller?.disconnectedInterval();
192
191
  /** Global event - always fire */
@@ -197,6 +196,8 @@ export default class IABookActions extends LitElement {
197
196
  composed: true,
198
197
  })
199
198
  );
199
+
200
+ // early return if book is already expired
200
201
  return;
201
202
  }
202
203
 
@@ -253,9 +254,17 @@ export default class IABookActions extends LitElement {
253
254
  */
254
255
  document.addEventListener('click', () => {
255
256
  if (this.loanRenewHelper && this.loanRenewResult.timeLeft > 0) {
256
- console.log('1');
257
+ console.log('clicked-outside');
257
258
  this.suppressToast = true;
258
259
  }
260
+
261
+ // reload when user click on page after it EXPIRED
262
+ const hasExpired =
263
+ 'browsingExpired' in this.lendingStatus &&
264
+ this.lendingStatus?.browsingExpired;
265
+ if (hasExpired) {
266
+ window.location?.reload();
267
+ }
259
268
  });
260
269
 
261
270
  /**
@@ -283,7 +292,6 @@ export default class IABookActions extends LitElement {
283
292
  );
284
293
 
285
294
  await this.loanRenewHelper.handleLoanRenew();
286
- // console.log(this.loanRenewResult.timeLeft);
287
295
  this.loanRenewResult = this.loanRenewHelper.result;
288
296
  }
289
297
 
@@ -366,6 +374,9 @@ export default class IABookActions extends LitElement {
366
374
 
367
375
  this.suppressToast = false;
368
376
  this.showToastMessage();
377
+
378
+ window?.Sentry?.captureMessage(sentryLogs.browseHasExpired);
379
+ console.log(sentryLogs.browseHasExpired);
369
380
  }
370
381
 
371
382
  /**
@@ -463,7 +474,14 @@ export default class IABookActions extends LitElement {
463
474
  await this.showToastMessage();
464
475
  await this.browseHasRenew();
465
476
  await this.resetTimerCountState();
466
- this.startLoanTokenPoller();
477
+
478
+ window?.Sentry?.captureMessage(`${sentryLogs.bookHasRenewed}`);
479
+
480
+ console.log(sentryLogs.bookHasRenewed, {
481
+ loanRenewResult: this.loanRenewResult,
482
+ browseHasRenew: this.lendingStatus.secondsLeftOnLoan,
483
+ resetTimerCountState: this._shadowRoot.querySelector('timer-countdown'),
484
+ });
467
485
  }
468
486
  }
469
487
 
@@ -472,7 +490,7 @@ export default class IABookActions extends LitElement {
472
490
  */
473
491
  startLoanTokenPoller() {
474
492
  if (this.tokenPoller) {
475
- window?.Sentry?.captureMessage('startLoanTokenPoller clearing interval');
493
+ window?.Sentry?.captureMessage(sentryLogs.clearTokenPoller);
476
494
  this.tokenPoller.disconnectedInterval();
477
495
  }
478
496
  const successCallback = () => {
@@ -529,6 +547,20 @@ export default class IABookActions extends LitElement {
529
547
 
530
548
  if (errorMsg) this.showErrorModal(errorMsg, action);
531
549
 
550
+ // if error related to loan token
551
+ // - clear tokenPoller interval
552
+ // - set user_has_browsed to `false`
553
+ if (action === 'create_token') {
554
+ this.tokenPoller.disconnectedInterval();
555
+
556
+ const currStatus = {
557
+ ...this.lendingStatus,
558
+ user_has_browsed: false,
559
+ available_to_browse: true,
560
+ };
561
+ this.lendingStatus = currStatus;
562
+ }
563
+
532
564
  // update action bar state if book is not available to browse or borrow.
533
565
  if (errorMsg && errorMsg.match(/not available to borrow/gm)) {
534
566
  let currStatus = this.lendingStatus;
@@ -584,7 +616,8 @@ export default class IABookActions extends LitElement {
584
616
  href="mailto:info@archive.org?subject=Help: cannot access my borrowed book: ${this
585
617
  .identifier}"
586
618
  >info@archive.org</a
587
- >`;
619
+ ><br /><br />
620
+ errorLog: ${errorMsg}`;
588
621
  }
589
622
 
590
623
  this.modal.showModal({