@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
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { html, fixture, expect, aTimeout } from '@open-wc/testing';
|
|
2
|
+
import '../../src/components/timer-countdown.js';
|
|
3
|
+
|
|
4
|
+
const container = ({ secondsLeftOnLoan, loanRenewTimeConfig } = {}) =>
|
|
5
|
+
html`<timer-countdown
|
|
6
|
+
.secondsLeftOnLoan=${secondsLeftOnLoan}
|
|
7
|
+
.loanRenewTimeConfig=${loanRenewTimeConfig}
|
|
8
|
+
></timer-countdown>`;
|
|
9
|
+
|
|
10
|
+
describe('<timer-countdown>', () => {
|
|
11
|
+
it('timer interval is undefined when loan is expired', async () => {
|
|
12
|
+
const el = await fixture(
|
|
13
|
+
container({
|
|
14
|
+
secondsLeftOnLoan: 0, // in seconds
|
|
15
|
+
loanRenewTimeConfig: {
|
|
16
|
+
loanTotalTime: 14, // in seconds
|
|
17
|
+
loanRenewAtLast: 5, // in seconds
|
|
18
|
+
pageChangedInLast: 5, // in seconds
|
|
19
|
+
isDevBox: true,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
await el.updateComplete;
|
|
25
|
+
expect(el.timerInterval).to.be.undefined;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('timer interval is not undefined when loan is active', async () => {
|
|
29
|
+
const el = await fixture(
|
|
30
|
+
container({
|
|
31
|
+
secondsLeftOnLoan: 2, // in seconds
|
|
32
|
+
loanRenewTimeConfig: {
|
|
33
|
+
loanTotalTime: 14, // in seconds
|
|
34
|
+
loanRenewAtLast: 5, // in seconds
|
|
35
|
+
pageChangedInLast: 5, // in seconds
|
|
36
|
+
isDevBox: true,
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
await aTimeout(1900);
|
|
42
|
+
await el.updateComplete;
|
|
43
|
+
|
|
44
|
+
expect(el.secondsLeftOnLoan).to.equal(2);
|
|
45
|
+
expect(el.timerInterval).to.not.be.undefined;
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -25,7 +25,7 @@ describe('Get Lending Actions', () => {
|
|
|
25
25
|
|
|
26
26
|
expect(actions.primaryTitle).to.equal(bookTitles.available_1hr);
|
|
27
27
|
expect(actions.primaryActions.length).to.equal(3);
|
|
28
|
-
expect(actions.primaryActions[0].text).to.equal('Borrow
|
|
28
|
+
expect(actions.primaryActions[0].text).to.equal('Borrow');
|
|
29
29
|
expect(actions.primaryActions[1].text).to.equal('Borrow for 14 days');
|
|
30
30
|
expect(actions.secondaryActions[1].text).to.equal('Purchase at');
|
|
31
31
|
});
|
|
@@ -111,7 +111,7 @@ describe('Get Lending Actions', () => {
|
|
|
111
111
|
expect(actions.primaryTitle).to.equal(bookTitles.claim_waitlist);
|
|
112
112
|
expect(actions.primaryActions.length).to.equal(3);
|
|
113
113
|
expect(actions.primaryActions[0].text).to.equal('Borrow for 14 days');
|
|
114
|
-
expect(actions.primaryActions[1].text).to.equal('Borrow
|
|
114
|
+
expect(actions.primaryActions[1].text).to.equal('Borrow');
|
|
115
115
|
expect(actions.primaryActions[2].text).to.equal('Leave Waitlist');
|
|
116
116
|
expect(spy.called).to.be.true;
|
|
117
117
|
});
|
|
@@ -138,7 +138,7 @@ describe('Get Lending Actions', () => {
|
|
|
138
138
|
expect(actions.primaryTitle).to.equal(bookTitles.on_waitlist);
|
|
139
139
|
expect(actions.primaryActions.length).to.equal(2);
|
|
140
140
|
expect(actions.primaryActions[0].text).to.equal('Leave Waitlist');
|
|
141
|
-
expect(actions.primaryActions[1].text).to.equal('Borrow
|
|
141
|
+
expect(actions.primaryActions[1].text).to.equal('Borrow');
|
|
142
142
|
expect(claimSpy.called).to.be.false;
|
|
143
143
|
expect(waitlistSpy.called).to.be.true;
|
|
144
144
|
});
|
|
@@ -162,7 +162,7 @@ describe('Get Lending Actions', () => {
|
|
|
162
162
|
expect(actions.primaryTitle).to.equal(bookTitles.on_waitlist);
|
|
163
163
|
expect(actions.primaryActions.length).to.equal(2);
|
|
164
164
|
expect(actions.primaryActions[0].text).to.equal('Leave Waitlist');
|
|
165
|
-
expect(actions.primaryActions[1].text).to.equal('Borrow
|
|
165
|
+
expect(actions.primaryActions[1].text).to.equal('Borrow');
|
|
166
166
|
expect(waitlistSpy.called).to.be.true;
|
|
167
167
|
});
|
|
168
168
|
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { expect, aTimeout } from '@open-wc/testing';
|
|
2
|
+
|
|
3
|
+
import { LocalCache } from '@internetarchive/local-cache';
|
|
4
|
+
import { LoanRenewHelper } from '../../../src/core/services/loan-renew-helper.js';
|
|
5
|
+
|
|
6
|
+
const identifier = 'booBar';
|
|
7
|
+
const loanRenewTimeConfig = {
|
|
8
|
+
loanTotalTime: 13,
|
|
9
|
+
loanRenewAtLast: 10,
|
|
10
|
+
pageChangedInLast: 12,
|
|
11
|
+
isDevBox: true,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// localCache used for auto-loan-renew
|
|
15
|
+
const localCache = new LocalCache({
|
|
16
|
+
namespace: 'loanRenew',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
beforeEach(async () => {
|
|
20
|
+
await localCache.set({
|
|
21
|
+
key: `${identifier}-loanTime`,
|
|
22
|
+
value: new Date(
|
|
23
|
+
new Date().getTime() + loanRenewTimeConfig.loanTotalTime * 1000
|
|
24
|
+
),
|
|
25
|
+
ttl: Number(loanRenewTimeConfig.loanTotalTime),
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('Loan Renew Determine', () => {
|
|
30
|
+
it('flip book page while reading a book', async () => {
|
|
31
|
+
await aTimeout(1500);
|
|
32
|
+
|
|
33
|
+
await localCache.set({
|
|
34
|
+
key: `${identifier}-pageChangedTime`,
|
|
35
|
+
value: new Date(), // current time
|
|
36
|
+
ttl: Number(loanRenewTimeConfig.loanTotalTime),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const loanRenewHelper = new LoanRenewHelper(
|
|
40
|
+
true, // hasPageChanged
|
|
41
|
+
identifier,
|
|
42
|
+
localCache,
|
|
43
|
+
loanRenewTimeConfig
|
|
44
|
+
);
|
|
45
|
+
await loanRenewHelper.handleLoanRenew();
|
|
46
|
+
|
|
47
|
+
expect(loanRenewHelper.result.renewNow).to.be.false;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('auto renewed book when user is currently reading', async () => {
|
|
51
|
+
await localCache.set({
|
|
52
|
+
key: `${identifier}-pageChangedTime`,
|
|
53
|
+
value: new Date(), // current time
|
|
54
|
+
ttl: Number(loanRenewTimeConfig.loanTotalTime),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
await aTimeout(1500);
|
|
58
|
+
|
|
59
|
+
const loanRenewHelper = new LoanRenewHelper(
|
|
60
|
+
false, // timer-countdown event
|
|
61
|
+
identifier,
|
|
62
|
+
localCache,
|
|
63
|
+
loanRenewTimeConfig
|
|
64
|
+
);
|
|
65
|
+
await loanRenewHelper.handleLoanRenew();
|
|
66
|
+
|
|
67
|
+
expect(loanRenewHelper.result.renewNow).to.be.true;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('get toast message template', async () => {
|
|
71
|
+
const loanRenewHelper = new LoanRenewHelper(
|
|
72
|
+
false,
|
|
73
|
+
identifier,
|
|
74
|
+
localCache,
|
|
75
|
+
loanRenewTimeConfig
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const toastMsg = loanRenewHelper.getMessageTexts(
|
|
79
|
+
loanRenewHelper.loanReturnWarning,
|
|
80
|
+
'65' // in seconds
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
expect(toastMsg).to.be.equal(
|
|
84
|
+
'This book will be automatically returned in 1 minute unless you turn a page.'
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -4,11 +4,17 @@ import '../src/ia-book-actions.js';
|
|
|
4
4
|
import Sinon from 'sinon';
|
|
5
5
|
|
|
6
6
|
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
|
7
|
+
import { LocalCache } from '@internetarchive/local-cache';
|
|
7
8
|
|
|
8
9
|
afterEach(() => {
|
|
9
10
|
Sinon.restore();
|
|
10
11
|
});
|
|
11
12
|
|
|
13
|
+
// localCache used for auto-loan-renew
|
|
14
|
+
const localCache = new LocalCache({
|
|
15
|
+
namespace: 'loanRenew',
|
|
16
|
+
});
|
|
17
|
+
|
|
12
18
|
const container = ({ userid, identifier, lendingStatus = {} } = {}) =>
|
|
13
19
|
html`<ia-book-actions
|
|
14
20
|
.userid=${userid}
|
|
@@ -81,7 +87,7 @@ describe('Primary Actions data', () => {
|
|
|
81
87
|
);
|
|
82
88
|
const expectedPrimaryActions = [
|
|
83
89
|
{
|
|
84
|
-
text: 'Borrow for 1 hour'
|
|
90
|
+
text: 'Borrow', // changed from 'Borrow for 1 hour'
|
|
85
91
|
callback: () => {},
|
|
86
92
|
className: 'ia-button primary',
|
|
87
93
|
},
|
|
@@ -161,7 +167,7 @@ describe('Borrow status actions', () => {
|
|
|
161
167
|
|
|
162
168
|
// removed available_to_borrow from lending bar
|
|
163
169
|
expect(el.lendingStatus.available_to_borrow).to.be.false;
|
|
164
|
-
expect(el.primaryActions[0].text).to.equal('Borrow
|
|
170
|
+
expect(el.primaryActions[0].text).to.equal('Borrow');
|
|
165
171
|
});
|
|
166
172
|
|
|
167
173
|
it('Check action for borrowable book without user', async () => {
|
|
@@ -182,9 +188,7 @@ describe('Borrow status actions', () => {
|
|
|
182
188
|
},
|
|
183
189
|
];
|
|
184
190
|
|
|
185
|
-
expect(el.primaryTitle).to.equal(
|
|
186
|
-
'Renewable every hour, pending availability.'
|
|
187
|
-
);
|
|
191
|
+
expect(el.primaryTitle).to.equal('');
|
|
188
192
|
expect(el.primaryActions.length).to.equal(2);
|
|
189
193
|
expect(el.primaryActions[0].text).to.equal('Log In and Borrow');
|
|
190
194
|
expect(el.primaryActions[0].text).to.equal(expectedPrimaryActions[0].text);
|
|
@@ -232,9 +236,14 @@ describe('Browsing expired status', () => {
|
|
|
232
236
|
},
|
|
233
237
|
})
|
|
234
238
|
);
|
|
235
|
-
expect(el.primaryTitle).contains('
|
|
239
|
+
expect(el.primaryTitle).contains('');
|
|
236
240
|
expect(el.primaryActions[0].text).to.equal('Return now');
|
|
237
241
|
expect(el.primaryActions[1].text).to.equal('Print Disability Access');
|
|
242
|
+
|
|
243
|
+
// default params of one-hour loan renew
|
|
244
|
+
expect(el.loanRenewResult.texts).to.equal('');
|
|
245
|
+
expect(el.loanRenewResult.renewNow).to.equal(false);
|
|
246
|
+
expect(el.loanRenewResult.secondsLeft).to.equal(0);
|
|
238
247
|
});
|
|
239
248
|
|
|
240
249
|
it('Book is browsing and going to expire after 1 second', async () => {
|
|
@@ -250,11 +259,23 @@ describe('Browsing expired status', () => {
|
|
|
250
259
|
})
|
|
251
260
|
);
|
|
252
261
|
|
|
262
|
+
// timer-countdown is still active
|
|
263
|
+
expect(el.shadowRoot.querySelector('timer-countdown')).to.not.be.null;
|
|
264
|
+
|
|
253
265
|
await aTimeout(1500); // wait for 1.5 second
|
|
254
266
|
await el.updateComplete;
|
|
255
267
|
|
|
256
|
-
expect(el.
|
|
257
|
-
|
|
268
|
+
expect(el.primaryActions[0].text).to.equal('Borrow');
|
|
269
|
+
|
|
270
|
+
// timer-countdown is gone now
|
|
271
|
+
expect(el.shadowRoot.querySelector('timer-countdown')).to.be.null;
|
|
272
|
+
|
|
273
|
+
// // book has been expired
|
|
274
|
+
expect(el.loanRenewResult.renewNow).to.equal(false);
|
|
275
|
+
expect(el.loanRenewResult.secondsLeft).to.equal(0);
|
|
276
|
+
expect(el.loanRenewResult.texts).to.equal(
|
|
277
|
+
'This book has been automatically returned due to inactivity.'
|
|
278
|
+
);
|
|
258
279
|
});
|
|
259
280
|
|
|
260
281
|
it('Expiring book cancels interval & emits event', async () => {
|
|
@@ -279,9 +300,8 @@ describe('Browsing expired status', () => {
|
|
|
279
300
|
el.lendingStatus = browsingStatus;
|
|
280
301
|
await el.updateComplete;
|
|
281
302
|
|
|
282
|
-
expect(el.primaryTitle).contains('
|
|
303
|
+
expect(el.primaryTitle).contains('');
|
|
283
304
|
expect(el.primaryActions[0].text).to.equal('Return now');
|
|
284
|
-
expect(el.tokenPoller.loanTokenInterval).to.not.equal(undefined);
|
|
285
305
|
|
|
286
306
|
const expiredStatus = { ...browsingStatus, browsingExpired: true };
|
|
287
307
|
el.lendingStatus = expiredStatus;
|
|
@@ -289,12 +309,55 @@ describe('Browsing expired status', () => {
|
|
|
289
309
|
await aTimeout(1500); // wait for 1.5 sec
|
|
290
310
|
|
|
291
311
|
expect(eventReceived).to.equal(true);
|
|
292
|
-
expect(el.
|
|
293
|
-
expect(el.primaryActions[0].text).to.equal('Borrow again');
|
|
312
|
+
expect(el.primaryActions[0].text).to.equal('Borrow');
|
|
294
313
|
expect(el.tokenPoller.loanTokenInterval).to.equal(undefined);
|
|
295
314
|
});
|
|
296
315
|
});
|
|
297
316
|
|
|
317
|
+
describe('Auto renew one hour loan', () => {
|
|
318
|
+
it('Book is browsing and renewed it now', async () => {
|
|
319
|
+
const el = await fixture(
|
|
320
|
+
container({
|
|
321
|
+
userid: '@userid',
|
|
322
|
+
identifier: 'Foo',
|
|
323
|
+
lendingStatus: {
|
|
324
|
+
is_lendable: true,
|
|
325
|
+
user_has_browsed: true,
|
|
326
|
+
browseHasExpired: false,
|
|
327
|
+
secondsLeftOnLoan: 12,
|
|
328
|
+
},
|
|
329
|
+
})
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
el.loanRenewResult = {
|
|
333
|
+
texts: 'This book has been renewed for 1 hour.',
|
|
334
|
+
renewNow: true,
|
|
335
|
+
secondsLeft: 10,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
await localCache.set({
|
|
339
|
+
key: `${el.identifier}-loanTime`,
|
|
340
|
+
value: new Date(new Date().getTime() + 10 * 1000),
|
|
341
|
+
ttl: Number(10),
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const myEvent = new CustomEvent('loanAutoRenewed');
|
|
345
|
+
el.addEventListener('loanAutoRenewed', () => {
|
|
346
|
+
el.handleLoanAutoRenewed();
|
|
347
|
+
});
|
|
348
|
+
el.dispatchEvent(myEvent);
|
|
349
|
+
|
|
350
|
+
await aTimeout(1500); // wait for 1.5 second
|
|
351
|
+
await el.updateComplete;
|
|
352
|
+
|
|
353
|
+
expect(el.loanRenewResult.texts).to.equal(
|
|
354
|
+
'This book has been renewed for 1 hour.'
|
|
355
|
+
);
|
|
356
|
+
expect(el.loanRenewResult.renewNow).to.equal(true);
|
|
357
|
+
expect(el.loanRenewResult.secondsLeft).to.equal(10);
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
|
|
298
361
|
describe('Shared Resize Observer', () => {
|
|
299
362
|
it('can receive a Shared Resize Observer', async () => {
|
|
300
363
|
const sharedObserverStub = new SharedResizeObserver();
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { css } from 'lit';
|
|
2
|
-
|
|
3
|
-
export default timerCountDownStyle = css`
|
|
4
|
-
:host {
|
|
5
|
-
right: 5px;
|
|
6
|
-
font-size: 14px;
|
|
7
|
-
position: absolute;
|
|
8
|
-
}
|
|
9
|
-
#countdown1 {
|
|
10
|
-
position: relative;
|
|
11
|
-
margin: auto;
|
|
12
|
-
margin-top: 100px;
|
|
13
|
-
height: 40px;
|
|
14
|
-
width: 40px;
|
|
15
|
-
text-align: center;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
#countdown-number {
|
|
19
|
-
color: white;
|
|
20
|
-
display: inline-block;
|
|
21
|
-
line-height: 40px;
|
|
22
|
-
margin-right: 12px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
svg {
|
|
26
|
-
position: absolute;
|
|
27
|
-
top: 0;
|
|
28
|
-
right: 0;
|
|
29
|
-
width: 40px;
|
|
30
|
-
height: 40px;
|
|
31
|
-
transform: rotateY(-180deg) rotateZ(-90deg);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
svg circle {
|
|
35
|
-
stroke-dasharray: 113px;
|
|
36
|
-
stroke-dashoffset: 0px;
|
|
37
|
-
stroke-linecap: round;
|
|
38
|
-
stroke-width: 3px;
|
|
39
|
-
stroke: white;
|
|
40
|
-
fill: none;
|
|
41
|
-
animation: countdown 60s linear infinite forwards;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@keyframes countdown {
|
|
45
|
-
from {
|
|
46
|
-
stroke-dashoffset: 0px;
|
|
47
|
-
}
|
|
48
|
-
to {
|
|
49
|
-
stroke-dashoffset: 113px;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
.hidden {
|
|
53
|
-
display: none;
|
|
54
|
-
}
|
|
55
|
-
.visible {
|
|
56
|
-
display: inline-block;
|
|
57
|
-
}
|
|
58
|
-
`;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { html, css, LitElement, nothing } from 'lit';
|
|
2
|
-
|
|
3
|
-
export class ToastMessage extends LitElement {
|
|
4
|
-
static get properties() {
|
|
5
|
-
return {
|
|
6
|
-
texts: { type: String },
|
|
7
|
-
dismisOnClick: { type: Boolean },
|
|
8
|
-
hideToast: { type: Boolean },
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
constructor() {
|
|
13
|
-
super();
|
|
14
|
-
this.texts = '';
|
|
15
|
-
this.textClass = '';
|
|
16
|
-
this.hideToast = false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
render() {
|
|
20
|
-
return !this.hideToast
|
|
21
|
-
? html`
|
|
22
|
-
<span
|
|
23
|
-
class="toast-message fade-in ${this.textClass}"
|
|
24
|
-
title="Click/tap to close"
|
|
25
|
-
@click=${() => { this.dismisOnClick ? this.hideToast = true : nothing}}
|
|
26
|
-
>${this.texts}</span>
|
|
27
|
-
`
|
|
28
|
-
: nothing;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static get styles() {
|
|
32
|
-
const heightFromTop = css`var(--messageHeightFromTop, 15%)`;
|
|
33
|
-
|
|
34
|
-
return css`
|
|
35
|
-
:host {
|
|
36
|
-
display: inline-block;
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
.toast-message {
|
|
40
|
-
z-index: 2;
|
|
41
|
-
position: absolute;
|
|
42
|
-
top: ${heightFromTop};
|
|
43
|
-
font-size: 1.4rem;
|
|
44
|
-
font-family: "Helvetica Neue";
|
|
45
|
-
color: #fff;
|
|
46
|
-
left: 50%;
|
|
47
|
-
background: #333;
|
|
48
|
-
border: 1px solid #fff;
|
|
49
|
-
border-radius: 5px;
|
|
50
|
-
box-shadow: 1px 1px 2px;
|
|
51
|
-
padding: 10px;
|
|
52
|
-
width: fit-content;
|
|
53
|
-
transform: translate(-50%, -50%);
|
|
54
|
-
cursor: pointer;
|
|
55
|
-
animation: fadeIn 5s;
|
|
56
|
-
@keyframes fadeIn {
|
|
57
|
-
0% {
|
|
58
|
-
opacity: 0;
|
|
59
|
-
}
|
|
60
|
-
100% {
|
|
61
|
-
opacity: 1;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.hidden {
|
|
67
|
-
display: none;
|
|
68
|
-
}
|
|
69
|
-
.visible {
|
|
70
|
-
display: inline-block;
|
|
71
|
-
}
|
|
72
|
-
`;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
window.customElements.define('toast-message', ToastMessage);
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import ActionsHandlerService from './actions-handler/actions-handler-service.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* This class is used to determine if use is eligible for auto renew loan.
|
|
5
|
-
*
|
|
6
|
-
* ActionsHandlerService is a function being used to execute
|
|
7
|
-
*/
|
|
8
|
-
export class OneHourAutoRenew {
|
|
9
|
-
constructor(pageClick, identifier, localCache, autoRenewConfig, userHasBrowsed) {
|
|
10
|
-
this.pageClick = pageClick;
|
|
11
|
-
this.identifier = identifier;
|
|
12
|
-
this.localCache = localCache;
|
|
13
|
-
this.autoRenewConfig = autoRenewConfig;
|
|
14
|
-
this.userHasBrowsed = userHasBrowsed;
|
|
15
|
-
|
|
16
|
-
// messages for auto return machenism
|
|
17
|
-
this.autoRenewMessage = 'This book has been renewed for another hour.';
|
|
18
|
-
this.autoReturnMessage = 'This book has been auto-returned due to inactivity.';
|
|
19
|
-
this.autoReturnWarning = 'This book will be auto-returned in 10 minutes unless you turn a page.';
|
|
20
|
-
|
|
21
|
-
// private props
|
|
22
|
-
this.resultRes = {
|
|
23
|
-
toastTexts: this.autoReturnMessage,
|
|
24
|
-
hideToast: true,
|
|
25
|
-
renewNow: false,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return this.handleBookAutoRenew();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async handleBookAutoRenew() {
|
|
32
|
-
try {
|
|
33
|
-
// if page is not flipped in last 15 minutes,
|
|
34
|
-
// instantaly renew it if user viewed new page in last 10 minutes
|
|
35
|
-
if (this.pageClick) {
|
|
36
|
-
console.log('page flipped!')
|
|
37
|
-
this.setPageFlippedTime();
|
|
38
|
-
return this.userFlippedBookPage(); // user clicked on page
|
|
39
|
-
} else {
|
|
40
|
-
console.log('auto checker!')
|
|
41
|
-
return this.autoCheckerTimer(); // auto checker at 50th minute
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.log(error)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async setPageFlippedTime() {
|
|
50
|
-
// set pageFlipTime time in localStorage
|
|
51
|
-
await this.localCache.set({
|
|
52
|
-
key: `${this.identifier}-pageFlipTime`,
|
|
53
|
-
value: new Date(), // current time
|
|
54
|
-
ttl: parseInt(this.autoRenewConfig.totalTime),
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async userFlippedBookPage() {
|
|
59
|
-
const {
|
|
60
|
-
totalTime, // 60
|
|
61
|
-
autoCheckAt, // 50
|
|
62
|
-
} = this.autoRenewConfig;
|
|
63
|
-
const currentDate = new Date();
|
|
64
|
-
const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
|
|
65
|
-
|
|
66
|
-
const lastTimeFrame = await this.changeTime(
|
|
67
|
-
loanTime,
|
|
68
|
-
totalTime - autoCheckAt,
|
|
69
|
-
'add'
|
|
70
|
-
); // 50 seconds
|
|
71
|
-
|
|
72
|
-
if (currentDate >= lastTimeFrame) {
|
|
73
|
-
console.log('1 YES NOW BORROW IT AGAIN NOW!');
|
|
74
|
-
this.resultRes.toastTexts = this.autoRenewMessage;
|
|
75
|
-
this.resultRes.browseAgainNow = true;
|
|
76
|
-
this.resultRes.hideToast = false;
|
|
77
|
-
this.resultRes.renewNow = true;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return this.resultRes;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async autoCheckerTimer() {
|
|
84
|
-
const currentDate = new Date();
|
|
85
|
-
const { FlippedInLast } = this.autoRenewConfig;
|
|
86
|
-
const lastPageFlipTime = await this.localCache.get(`${this.identifier}-pageFlipTime`);
|
|
87
|
-
|
|
88
|
-
// last 15 min if used flipped a page.
|
|
89
|
-
const lastFlipTimeFrame = await this.changeTime(
|
|
90
|
-
currentDate,
|
|
91
|
-
FlippedInLast,
|
|
92
|
-
'sub'
|
|
93
|
-
); // 15 seconds
|
|
94
|
-
|
|
95
|
-
if (lastPageFlipTime === undefined || lastPageFlipTime <= lastFlipTimeFrame) { // not viewed
|
|
96
|
-
console.log('2 not viewed, warning message!');
|
|
97
|
-
this.resultRes.toastTexts = this.autoReturnWarning;
|
|
98
|
-
this.resultRes.hideToast = false;
|
|
99
|
-
} else if (lastPageFlipTime >= lastFlipTimeFrame) { // viewed in last time frame
|
|
100
|
-
console.log('3 viewed, auto renew and message!');
|
|
101
|
-
this.resultRes.toastTexts = this.autoRenewMessage;
|
|
102
|
-
this.resultRes.browseAgainNow = true;
|
|
103
|
-
this.resultRes.hideToast = false;
|
|
104
|
-
this.resultRes.renewNow = true;
|
|
105
|
-
|
|
106
|
-
// delete pageFlipTime when book is auto renew at nth minute
|
|
107
|
-
await this.localCache.delete(`${this.identifier}-pageFlipTime`);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return this.resultRes;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async changeTime(date, minutes, op) {
|
|
114
|
-
if (date === undefined) return undefined;
|
|
115
|
-
|
|
116
|
-
if (op === 'sub') {
|
|
117
|
-
return new Date(date.getTime() - minutes * 1000);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return new Date(date.getTime() + minutes * 1000);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
sendEvent(eventCategory, eventAction) {
|
|
125
|
-
window?.archive_analytics?.send_event(
|
|
126
|
-
eventCategory,
|
|
127
|
-
eventAction,
|
|
128
|
-
`identifier=${this.identifier}`
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async handleAutoRenew() {
|
|
133
|
-
const action = 'renew_loan';
|
|
134
|
-
ActionsHandlerService({
|
|
135
|
-
identifier: this.identifier,
|
|
136
|
-
action,
|
|
137
|
-
error: data => {
|
|
138
|
-
window?.Sentry?.captureMessage(
|
|
139
|
-
'handleAutoRenew error',
|
|
140
|
-
JSON.stringify(data)
|
|
141
|
-
);
|
|
142
|
-
// this.errorCallback({ detail: { action, data } });
|
|
143
|
-
// send LendingServiceError to GA
|
|
144
|
-
this.sendEvent('handleAutoRenew', action);
|
|
145
|
-
},
|
|
146
|
-
success: () => {
|
|
147
|
-
console.log('success!');
|
|
148
|
-
return 'success';
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|