@internetarchive/ia-book-actions 0.0.29-alpha4 → 0.0.29-alpha40
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 +41 -33
- package/package.json +13 -5
- package/src/assets/styles/collapsible-action-group.js +2 -1
- package/src/components/collapsible-action-group.js +25 -12
- package/src/components/info-icon.js +0 -9
- package/src/components/text-group.js +1 -1
- package/src/components/timer-countdown.js +85 -75
- package/src/core/config/analytics-event-and-category.js +1 -0
- package/src/core/config/sentry-events.js +20 -0
- package/src/core/services/actions-config.js +2 -2
- package/src/core/services/actions-handler/actions-handler-service.js +5 -2
- package/src/core/services/actions-handler/actions-handler.js +46 -35
- package/src/core/services/get-lending-actions.js +6 -11
- package/src/core/services/loan-renew-helper.js +163 -0
- package/src/core/services/loan-token-poller.js +19 -10
- package/src/ia-book-actions.js +323 -135
- package/test/components/collapsible-action-group.test.js +2 -2
- package/test/components/timer-countdown.test.js +47 -0
- package/test/core/services/get-lending-actions.test.js +4 -4
- package/test/core/services/loan-renew-helper.test.js +87 -0
- package/test/ia-book-actions.test.js +75 -12
- package/src/assets/styles/timer-countdown.js +0 -58
- package/src/components/toast-message.js +0 -76
- package/src/core/services/one-hour-auto-renew.js +0 -152
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
|
|
3
|
-
import { LocalCache } from '@internetarchive/local-cache';
|
|
4
3
|
import { URLHelper } from '../../config/url-helper.js';
|
|
4
|
+
import { sentryLogs } from '../../config/sentry-events.js';
|
|
5
|
+
|
|
5
6
|
import ActionsHandlerService from './actions-handler-service.js';
|
|
6
7
|
import * as Cookies from '../doc-cookies.js';
|
|
7
8
|
|
|
@@ -16,14 +17,12 @@ import * as Cookies from '../doc-cookies.js';
|
|
|
16
17
|
export default class ActionsHandler extends LitElement {
|
|
17
18
|
constructor() {
|
|
18
19
|
super();
|
|
19
|
-
this.identifier = '';
|
|
20
|
-
this.ajaxTimeout = 6000;
|
|
21
|
-
this.returnUrl = '';
|
|
22
|
-
this.autoRenewConfig = {};
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
/**
|
|
22
|
+
* wait untill borrow is complete, then refresh the page
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
this.waitUntillBorrowComplete = 6; // in seconds
|
|
27
26
|
|
|
28
27
|
this.bindEvents();
|
|
29
28
|
}
|
|
@@ -36,7 +35,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
36
35
|
);
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
bindEvents() {
|
|
40
39
|
this.addEventListener('browseBook', ({ detail }) => {
|
|
41
40
|
this.handleBrowseIt();
|
|
42
41
|
this.setConsecutiveLoanCounts();
|
|
@@ -51,9 +50,8 @@ export default class ActionsHandler extends LitElement {
|
|
|
51
50
|
this.sendEvent(category, action);
|
|
52
51
|
});
|
|
53
52
|
|
|
54
|
-
this.addEventListener('
|
|
55
|
-
|
|
56
|
-
this.handleAutoBrowseIt();
|
|
53
|
+
this.addEventListener('loanRenew', ({ detail }) => {
|
|
54
|
+
this.handleLoanRenew();
|
|
57
55
|
const { category, action } = detail.event;
|
|
58
56
|
this.sendEvent(category, action);
|
|
59
57
|
});
|
|
@@ -112,12 +110,12 @@ export default class ActionsHandler extends LitElement {
|
|
|
112
110
|
handleBrowseIt() {
|
|
113
111
|
const action = 'browse_book';
|
|
114
112
|
this.dispatchToggleActionGroup();
|
|
115
|
-
this.setBrowseTimeSession()
|
|
116
113
|
|
|
117
114
|
ActionsHandlerService({
|
|
118
115
|
action,
|
|
119
116
|
identifier: this.identifier,
|
|
120
117
|
success: () => {
|
|
118
|
+
this.setBrowseTimeSession();
|
|
121
119
|
this.handleReadItNow();
|
|
122
120
|
},
|
|
123
121
|
error: data => {
|
|
@@ -126,25 +124,26 @@ export default class ActionsHandler extends LitElement {
|
|
|
126
124
|
});
|
|
127
125
|
}
|
|
128
126
|
|
|
129
|
-
|
|
127
|
+
handleLoanRenew() {
|
|
130
128
|
const action = 'renew_loan';
|
|
131
|
-
this.setBrowseTimeSession()
|
|
132
129
|
|
|
133
130
|
ActionsHandlerService({
|
|
134
131
|
action,
|
|
135
132
|
identifier: this.identifier,
|
|
136
|
-
success:
|
|
137
|
-
|
|
133
|
+
success: data => {
|
|
134
|
+
this.setBrowseTimeSession();
|
|
135
|
+
this.dispatchEvent(
|
|
136
|
+
new CustomEvent('loanAutoRenewed', {
|
|
137
|
+
detail: { action, data },
|
|
138
|
+
})
|
|
139
|
+
);
|
|
138
140
|
},
|
|
139
141
|
error: data => {
|
|
140
|
-
console.log(data);
|
|
141
|
-
console.log('error!');
|
|
142
142
|
this.dispatchActionError(action, data);
|
|
143
143
|
},
|
|
144
144
|
});
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
|
|
148
147
|
handleReturnIt() {
|
|
149
148
|
const action = 'return_loan';
|
|
150
149
|
this.dispatchToggleActionGroup();
|
|
@@ -269,7 +268,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
269
268
|
// redirection on details page after 5 seconds because borrowing book takes time to create item creation.
|
|
270
269
|
setTimeout(() => {
|
|
271
270
|
URLHelper.goToUrl(redirectTo, true);
|
|
272
|
-
}, this.
|
|
271
|
+
}, this.waitUntillBorrowComplete * 1000);
|
|
273
272
|
}
|
|
274
273
|
|
|
275
274
|
// save consecutive loan count for borrow
|
|
@@ -290,11 +289,36 @@ export default class ActionsHandler extends LitElement {
|
|
|
290
289
|
// set new value
|
|
291
290
|
Cookies.setItem(storageKey, newCount, date, '/');
|
|
292
291
|
} catch (error) {
|
|
293
|
-
window?.Sentry?.captureException(
|
|
292
|
+
window?.Sentry?.captureException(
|
|
293
|
+
`${sentryLogs.setConsecutiveLoanCounts} - Error: ${error}`
|
|
294
|
+
);
|
|
294
295
|
this.sendEvent('Cookies-Error-Actions', error);
|
|
295
296
|
}
|
|
296
297
|
}
|
|
297
298
|
|
|
299
|
+
/**
|
|
300
|
+
* set browse time in indexedDB
|
|
301
|
+
*/
|
|
302
|
+
async setBrowseTimeSession() {
|
|
303
|
+
try {
|
|
304
|
+
const expireDate = new Date(
|
|
305
|
+
new Date().getTime() + this.loanTotalTime * 1000
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
// set a value
|
|
309
|
+
await this.localCache.set({
|
|
310
|
+
key: `${this.identifier}-loanTime`,
|
|
311
|
+
value: expireDate,
|
|
312
|
+
ttl: Number(this.loanTotalTime),
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// delete pageChangedTime when book is auto renew at nth minute
|
|
316
|
+
await this.localCache.delete(`${this.identifier}-pageChangedTime`);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.log(error);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
298
322
|
deleteLoanCookies() {
|
|
299
323
|
const date = new Date();
|
|
300
324
|
date.setTime(date.getTime() - 24 * 60 * 60 * 1000); // one day ago
|
|
@@ -314,17 +338,4 @@ export default class ActionsHandler extends LitElement {
|
|
|
314
338
|
'.archive.org'
|
|
315
339
|
);
|
|
316
340
|
}
|
|
317
|
-
|
|
318
|
-
async setBrowseTimeSession() {
|
|
319
|
-
try {
|
|
320
|
-
// set a value
|
|
321
|
-
await this.localCache.set({
|
|
322
|
-
key: `${this.identifier}-loanTime`,
|
|
323
|
-
value: new Date(), // current time
|
|
324
|
-
ttl: parseInt(this.autoRenewConfig.totalTime),
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
await this.localCache.delete(`${this.identifier}-pageFlipTime`);
|
|
328
|
-
} catch (error) {}
|
|
329
|
-
}
|
|
330
341
|
}
|
|
@@ -19,7 +19,7 @@ import ActionsConfig from './actions-config.js';
|
|
|
19
19
|
*
|
|
20
20
|
* Response of this class contain an object as follows:-
|
|
21
21
|
* {
|
|
22
|
-
* primaryTitle: '
|
|
22
|
+
* primaryTitle: '',
|
|
23
23
|
* primaryActions: [this.actionsConfig.returnBookConfig()],
|
|
24
24
|
* primaryColor: 'primary',
|
|
25
25
|
* secondaryActions: [this.actionsConfig.purchaseConfig()],
|
|
@@ -40,7 +40,7 @@ import ActionsConfig from './actions-config.js';
|
|
|
40
40
|
* @enum {string}
|
|
41
41
|
*/
|
|
42
42
|
export const bookTitles = {
|
|
43
|
-
available_1hr: '
|
|
43
|
+
available_1hr: '',
|
|
44
44
|
available_14d: 'This book can be borrowed for 14 days.',
|
|
45
45
|
available_pd: 'Book available to patrons with print disabilities.',
|
|
46
46
|
available_waitlist: 'A waitlist is available.',
|
|
@@ -49,7 +49,7 @@ export const bookTitles = {
|
|
|
49
49
|
being_borrowed: 'Another patron is using this book. Please check back later.',
|
|
50
50
|
eligible_pd: 'You are eligible for print-disabled access.',
|
|
51
51
|
on_waitlist: 'You are on the waitlist for this book.',
|
|
52
|
-
session_expired: '
|
|
52
|
+
session_expired: '',
|
|
53
53
|
unavailable: 'This book is not available at this time.',
|
|
54
54
|
};
|
|
55
55
|
|
|
@@ -98,7 +98,7 @@ export class GetLendingActions {
|
|
|
98
98
|
let isBrowsing =
|
|
99
99
|
lendingStatus.user_has_browsed && !lendingStatus.browsingExpired;
|
|
100
100
|
if (isBrowsing) {
|
|
101
|
-
primaryTitleText =
|
|
101
|
+
primaryTitleText = '';
|
|
102
102
|
} else {
|
|
103
103
|
primaryTitleText = `Your loan of this book has ${lendingStatus.daysLeftOnLoan} days left.`;
|
|
104
104
|
}
|
|
@@ -251,13 +251,6 @@ export class GetLendingActions {
|
|
|
251
251
|
borrow1HrAction() {
|
|
252
252
|
const lendingStatus = this.lendingStatus || {};
|
|
253
253
|
|
|
254
|
-
const possibleTitles = {
|
|
255
|
-
one_hour: 'Renewable every hour, pending availability.',
|
|
256
|
-
session_tryagain:
|
|
257
|
-
'Another patron is using this book. Please check back later.',
|
|
258
|
-
session_expired: 'Your loan has expired.',
|
|
259
|
-
};
|
|
260
|
-
|
|
261
254
|
// assess borrowable state
|
|
262
255
|
const browsingHasExpired =
|
|
263
256
|
!lendingStatus.available_to_browse && lendingStatus.browsingExpired;
|
|
@@ -364,6 +357,8 @@ export class GetLendingActions {
|
|
|
364
357
|
}
|
|
365
358
|
|
|
366
359
|
/**
|
|
360
|
+
* @deprecated
|
|
361
|
+
*
|
|
367
362
|
* Builds the countdown toolbar title.
|
|
368
363
|
*
|
|
369
364
|
* @return string innerHTML for the dialogOpts title attribute
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { nothing } from 'lit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This class is used to determine if use is eligible for auto renew loan.
|
|
5
|
+
*/
|
|
6
|
+
export class LoanRenewHelper {
|
|
7
|
+
constructor(hasPageChanged, identifier, localCache, loanRenewTimeConfig) {
|
|
8
|
+
this.hasPageChanged = hasPageChanged;
|
|
9
|
+
this.identifier = identifier;
|
|
10
|
+
this.localCache = localCache;
|
|
11
|
+
this.loanRenewTimeConfig = loanRenewTimeConfig;
|
|
12
|
+
|
|
13
|
+
// messages for auto return machenism
|
|
14
|
+
this.loanRenewMessage = 'This book has been renewed for 1 hour.';
|
|
15
|
+
this.loanReturnWarning =
|
|
16
|
+
'This book will be automatically returned in #time #unitsOfTime unless you turn a page.';
|
|
17
|
+
|
|
18
|
+
// private props
|
|
19
|
+
this.result = {
|
|
20
|
+
texts: null,
|
|
21
|
+
renewNow: false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
handleLoanRenew() {
|
|
26
|
+
try {
|
|
27
|
+
if (this.hasPageChanged) {
|
|
28
|
+
return this.pageChanged(); // user clicked on page
|
|
29
|
+
}
|
|
30
|
+
return this.autoChecker(); // auto checker at last 10th minute
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.log(error);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return nothing;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Trigger this function when user has browsed a book and change the post
|
|
40
|
+
* - every time user change the page, we set current time in indexedDB
|
|
41
|
+
* - also check if need to auto renew current loan
|
|
42
|
+
*
|
|
43
|
+
* @returns {this.result}
|
|
44
|
+
*/
|
|
45
|
+
async pageChanged() {
|
|
46
|
+
const {
|
|
47
|
+
loanTotalTime, // 60
|
|
48
|
+
loanRenewAtLast, // 50
|
|
49
|
+
} = this.loanRenewTimeConfig;
|
|
50
|
+
const currentTime = new Date();
|
|
51
|
+
const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
|
|
52
|
+
|
|
53
|
+
const lastTimeFrame = this.changeTime(
|
|
54
|
+
loanTime,
|
|
55
|
+
loanTotalTime - loanRenewAtLast,
|
|
56
|
+
'add'
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// if user viewed new page in last 10 minutes, renew immediately
|
|
60
|
+
if (lastTimeFrame !== null && currentTime >= lastTimeFrame) {
|
|
61
|
+
this.result.texts = this.loanRenewMessage;
|
|
62
|
+
this.result.renewNow = true;
|
|
63
|
+
console.log('manually renewed by page click!');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.setPageChangedTime();
|
|
67
|
+
return this.result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
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
|
+
*
|
|
74
|
+
* @returns {this.result}
|
|
75
|
+
*/
|
|
76
|
+
async autoChecker() {
|
|
77
|
+
const { pageChangedInLast } = this.loanRenewTimeConfig;
|
|
78
|
+
const pageChangedTime = await this.localCache.get(
|
|
79
|
+
`${this.identifier}-pageChangedTime`
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// in last 15 min if user make any activity.
|
|
83
|
+
const pageChangeTimeFrame = this.changeTime(
|
|
84
|
+
new Date(),
|
|
85
|
+
pageChangedInLast,
|
|
86
|
+
'sub'
|
|
87
|
+
); // 15 seconds
|
|
88
|
+
|
|
89
|
+
if (
|
|
90
|
+
pageChangedTime === undefined ||
|
|
91
|
+
pageChangedTime <= pageChangeTimeFrame
|
|
92
|
+
) {
|
|
93
|
+
this.result.texts = this.loanReturnWarning;
|
|
94
|
+
this.result.renewNow = false; // not viewed
|
|
95
|
+
} else if (pageChangedTime >= pageChangeTimeFrame) {
|
|
96
|
+
this.result.texts = '';
|
|
97
|
+
this.result.renewNow = true; // viewed in last time frame
|
|
98
|
+
console.log('silently renewed!');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return this.result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* set current time in indexedDB when user viewed a new page
|
|
106
|
+
*/
|
|
107
|
+
async setPageChangedTime() {
|
|
108
|
+
await this.localCache.set({
|
|
109
|
+
key: `${this.identifier}-pageChangedTime`,
|
|
110
|
+
value: new Date(), // current time
|
|
111
|
+
ttl: Number(this.loanRenewTimeConfig.loanTotalTime),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Texts we want to show in toast template including remaining time
|
|
117
|
+
* - eg. 1 minute, 50 seconds
|
|
118
|
+
*
|
|
119
|
+
* @param {String} texts
|
|
120
|
+
* @param {Number} time
|
|
121
|
+
*
|
|
122
|
+
* @returns {String} // texts will be appear in toast template
|
|
123
|
+
*/
|
|
124
|
+
getMessageTexts(texts, time) {
|
|
125
|
+
let unitOfTime = 'second';
|
|
126
|
+
|
|
127
|
+
let toastTexts = texts;
|
|
128
|
+
let timeLeft = time;
|
|
129
|
+
|
|
130
|
+
if (timeLeft > 60) {
|
|
131
|
+
unitOfTime = 'minute';
|
|
132
|
+
timeLeft = Math.floor(timeLeft / 60);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// replace remaining time
|
|
136
|
+
toastTexts = toastTexts?.replace(/#time/, timeLeft);
|
|
137
|
+
|
|
138
|
+
// replace unitsOfTime eg second vs seconds / minute vs /minutes
|
|
139
|
+
return toastTexts?.replace(
|
|
140
|
+
/#unitsOfTime/,
|
|
141
|
+
timeLeft !== 1 ? `${unitOfTime}s` : unitOfTime
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Helper function to get time difference
|
|
147
|
+
*
|
|
148
|
+
* @param {Date} date
|
|
149
|
+
* @param {Number} seconds
|
|
150
|
+
* @param {String} op - like sub, add, mul, sub
|
|
151
|
+
*
|
|
152
|
+
* @returns {Object} Date
|
|
153
|
+
*/
|
|
154
|
+
changeTime(date, seconds, op) {
|
|
155
|
+
if (date === undefined) return null;
|
|
156
|
+
|
|
157
|
+
if (op === 'sub') {
|
|
158
|
+
return new Date(date.getTime() - seconds * 1000);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return new Date(date.getTime() + seconds * 1000);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -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
|
/**
|
|
@@ -12,10 +14,10 @@ export class LoanTokenPoller {
|
|
|
12
14
|
this.borrowType = borrowType;
|
|
13
15
|
this.successCallback = successCallback; // callback function to be called after loan token is created
|
|
14
16
|
this.errorCallback = errorCallback; // callback function to be called after loan token is created
|
|
15
|
-
this.pollerDelay = pollerDelay; // value in
|
|
17
|
+
this.pollerDelay = pollerDelay; // value in seconds
|
|
16
18
|
|
|
17
19
|
this.loanTokenInterval = undefined;
|
|
18
|
-
this.
|
|
20
|
+
this.bookAccessed();
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
disconnectedInterval() {
|
|
@@ -31,7 +33,7 @@ export class LoanTokenPoller {
|
|
|
31
33
|
// }
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
async
|
|
36
|
+
async bookAccessed() {
|
|
35
37
|
let consecutiveLoanCounts = 1;
|
|
36
38
|
|
|
37
39
|
if (this.borrowType) {
|
|
@@ -43,7 +45,9 @@ export class LoanTokenPoller {
|
|
|
43
45
|
);
|
|
44
46
|
consecutiveLoanCounts = existingCount ?? 1;
|
|
45
47
|
} catch (error) {
|
|
46
|
-
window?.Sentry?.captureException(
|
|
48
|
+
window?.Sentry?.captureException(
|
|
49
|
+
`${sentryLogs.enableBookAcces} - CookieError: ${error}`
|
|
50
|
+
);
|
|
47
51
|
this.sendEvent('Cookies-Error-Token', error);
|
|
48
52
|
}
|
|
49
53
|
}
|
|
@@ -57,7 +61,7 @@ export class LoanTokenPoller {
|
|
|
57
61
|
if (this.borrowType !== 'adminBorrowed') {
|
|
58
62
|
this.loanTokenInterval = setInterval(() => {
|
|
59
63
|
this.handleLoanTokenPoller();
|
|
60
|
-
}, this.pollerDelay);
|
|
64
|
+
}, this.pollerDelay * 1000);
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
// event category and action for browsing book access
|
|
@@ -68,7 +72,10 @@ export class LoanTokenPoller {
|
|
|
68
72
|
|
|
69
73
|
this.sendEvent(category, action);
|
|
70
74
|
} else {
|
|
71
|
-
window?.Sentry?.captureMessage(
|
|
75
|
+
window?.Sentry?.captureMessage(
|
|
76
|
+
`${sentryLogs.bookAccessed} - 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
|
},
|