@internetarchive/ia-book-actions 0.0.29-alpha5 → 0.0.29-alpha51
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 +39 -34
- package/package.json +8 -6
- package/src/assets/data/lending-get-status-service.js +1 -1
- 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 +133 -74
- 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 +39 -27
- 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 +320 -139
- package/test/components/collapsible-action-group.test.js +2 -2
- package/test/components/timer-countdown.test.js +45 -0
- package/test/core/services/get-lending-actions.test.js +4 -4
- package/test/core/services/loan-renew-helper.test.js +86 -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 -154
package/demo/index.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
16
16
|
}
|
|
17
17
|
#demo {
|
|
18
|
-
height:
|
|
18
|
+
height: 100px;
|
|
19
19
|
}
|
|
20
20
|
ia-book-actions {
|
|
21
21
|
--white: #fff;
|
|
@@ -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
|
}
|
|
@@ -87,6 +91,7 @@
|
|
|
87
91
|
|
|
88
92
|
<script type="module">
|
|
89
93
|
/* eslint-disable */
|
|
94
|
+
|
|
90
95
|
import '../src/ia-book-actions.js';
|
|
91
96
|
import {
|
|
92
97
|
defaultLendingStatus,
|
|
@@ -96,7 +101,7 @@
|
|
|
96
101
|
import { LocalCache } from '@internetarchive/local-cache';
|
|
97
102
|
|
|
98
103
|
const localCache = new LocalCache({
|
|
99
|
-
namespace: '
|
|
104
|
+
namespace: 'loanRenew',
|
|
100
105
|
defaultTTL: 1 * 60, // 1 minute
|
|
101
106
|
});
|
|
102
107
|
|
|
@@ -104,10 +109,6 @@
|
|
|
104
109
|
const identifier = 'naturalhistoryof00unse_4111';
|
|
105
110
|
let bwbPurchaseUrl = 'https://www.betterworldbooks.com/product/detail/cambridge-ancient-hist-v04-0521044863';
|
|
106
111
|
|
|
107
|
-
let iaBookActions = document.querySelector('ia-book-actions');
|
|
108
|
-
|
|
109
|
-
// for debugging
|
|
110
|
-
window.iaBookActions = iaBookActions;
|
|
111
112
|
|
|
112
113
|
const modalConfig = new ModalConfig();
|
|
113
114
|
modalConfig.headerColor = '#d9534f';
|
|
@@ -117,6 +118,8 @@
|
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
121
|
+
let iaBookActions = document.querySelector('ia-book-actions');
|
|
122
|
+
|
|
120
123
|
iaBookActions.userid = userid;
|
|
121
124
|
iaBookActions.identifier = identifier;
|
|
122
125
|
iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
|
|
@@ -124,17 +127,18 @@
|
|
|
124
127
|
iaBookActions.bwbPurchaseUrl = '';
|
|
125
128
|
iaBookActions.modalConfig = modalConfig;
|
|
126
129
|
iaBookActions.lendingBarPostInit = lendingBarPostInit;
|
|
127
|
-
iaBookActions.tokenDelay =
|
|
130
|
+
iaBookActions.tokenDelay = 2; // 2 seconds
|
|
128
131
|
iaBookActions.returnUrl = 'https://openlibrary.org';
|
|
129
132
|
iaBookActions.localCache = localCache;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
|
|
134
|
+
let loanTotalTime2Min = { loanTotalTime: 20, loanRenewAtLast: 15, pageChangedInLast: 15 };
|
|
135
|
+
let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 180, pageChangedInLast: 15 };
|
|
136
|
+
let loanTotalTime1Hour = { loanTotalTime: 3600, loanRenewAtLast: 600, pageChangedInLast: 900 };
|
|
137
|
+
|
|
138
|
+
iaBookActions.loanRenewTimeConfig = loanTotalTime2Min;
|
|
135
139
|
|
|
136
140
|
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
137
|
-
let secondsLeftOnLoan = iaBookActions.
|
|
141
|
+
let secondsLeftOnLoan = iaBookActions.loanRenewTimeConfig.loanTotalTime;
|
|
138
142
|
|
|
139
143
|
document.querySelectorAll('.titleBar input[type=checkbox]').forEach((item) => {
|
|
140
144
|
item.addEventListener('click', (e) => {
|
|
@@ -146,21 +150,6 @@
|
|
|
146
150
|
});
|
|
147
151
|
});
|
|
148
152
|
|
|
149
|
-
document.querySelectorAll('.autoRenew input[type=checkbox]').forEach((item) => {
|
|
150
|
-
item.addEventListener('click', (e) => {
|
|
151
|
-
if (e.target.checked) {
|
|
152
|
-
iaBookActions.autoRenew = true;
|
|
153
|
-
iaBookActions.resetTimerCountdown = true;
|
|
154
|
-
lendingStatus1.secondsLeftOnLoan = secondsLeftOnLoan;
|
|
155
|
-
} else {
|
|
156
|
-
iaBookActions.autoRenew = false;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
let lending = {...defaultLendingStatus, ...lendingStatus1};
|
|
160
|
-
iaBookActions.lendingStatus = lending;
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
153
|
document.querySelectorAll('.errorEnable input[type=checkbox]').forEach((item) => {
|
|
165
154
|
if (window.location.href.indexOf('?error=true') !== -1) {
|
|
166
155
|
item.checked = true;
|
|
@@ -226,10 +215,10 @@
|
|
|
226
215
|
await localCache.set({
|
|
227
216
|
key: `${identifier}-loanTime`,
|
|
228
217
|
value: new Date(), // current time
|
|
229
|
-
ttl: Number(iaBookActions.
|
|
230
|
-
})
|
|
218
|
+
ttl: Number(iaBookActions.loanRenewTimeConfig.loanTotalTime),
|
|
219
|
+
});
|
|
231
220
|
|
|
232
|
-
await localCache.delete(`${identifier}-
|
|
221
|
+
await localCache.delete(`${identifier}-pageChangedTime`);
|
|
233
222
|
} catch (error) {}
|
|
234
223
|
|
|
235
224
|
} else if(e.target.value === 'browsingExpired') {
|
|
@@ -242,8 +231,11 @@
|
|
|
242
231
|
lendingStatus1.user_has_browsed = false;
|
|
243
232
|
}
|
|
244
233
|
|
|
245
|
-
|
|
246
|
-
|
|
234
|
+
// wait for a while
|
|
235
|
+
setTimeout(() => {
|
|
236
|
+
let lending = {...defaultLendingStatus, ...lendingStatus1};
|
|
237
|
+
iaBookActions.lendingStatus = lending;
|
|
238
|
+
}, 10);
|
|
247
239
|
});
|
|
248
240
|
});
|
|
249
241
|
|
|
@@ -292,6 +284,17 @@
|
|
|
292
284
|
iaBookActions.bwbPurchaseUrl = bwbPurchaseUrl;
|
|
293
285
|
})
|
|
294
286
|
});
|
|
287
|
+
|
|
288
|
+
document.querySelector('.pageChangedEvent').addEventListener('click', () => {
|
|
289
|
+
// dispatch event to say book page has flipped
|
|
290
|
+
document.querySelector('ia-book-actions').dispatchEvent(
|
|
291
|
+
new CustomEvent('BookReader:userAction', {
|
|
292
|
+
detail: {},
|
|
293
|
+
bubbles: true,
|
|
294
|
+
composed: true,
|
|
295
|
+
})
|
|
296
|
+
);
|
|
297
|
+
})
|
|
295
298
|
</script>
|
|
296
299
|
|
|
297
300
|
<div>
|
|
@@ -302,6 +305,9 @@
|
|
|
302
305
|
<td class="titleBar">
|
|
303
306
|
<label><input type="checkbox" name="title" value="title" />Title Bar</label>
|
|
304
307
|
</td>
|
|
308
|
+
<td>
|
|
309
|
+
<button class="pageChangedEvent">Page Change Event</button>
|
|
310
|
+
</td>
|
|
305
311
|
</tr>
|
|
306
312
|
</table>
|
|
307
313
|
</fieldset>
|
|
@@ -311,7 +317,6 @@
|
|
|
311
317
|
<table class="initial">
|
|
312
318
|
<tr colspan='5'>
|
|
313
319
|
<td class="errorEnable"><label><input type="checkbox" name="errorEnable" value="errorEnable" />Do you want to see error response?</label></td>
|
|
314
|
-
<td class="autoRenew"><label><input type="checkbox" name="autoRenew" value="autoRenew" />Do you want to auto-renew 1 hour</label></td>
|
|
315
320
|
</tr>
|
|
316
321
|
<tr>
|
|
317
322
|
<td class="userState">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "0.0.29-
|
|
3
|
+
"version": "0.0.29-alpha51",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -11,18 +11,19 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"start": "web-dev-server",
|
|
14
|
-
"lint": "eslint --ext .js",
|
|
15
|
-
"format": "eslint --ext .js
|
|
14
|
+
"lint": "eslint --ext .js,.html . --ignore-path .gitignore && prettier \"**/*.js\" --check --ignore-path .gitignore",
|
|
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
17
|
"test:fast": "web-test-runner --coverage --playwright --browsers chromium firefox webkit",
|
|
18
18
|
"test:watch": "web-test-runner --watch --playwright --browsers chromium firefox webkit"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@internetarchive/icon-info": "^1.2.6",
|
|
22
|
-
"@internetarchive/local-cache": "^0.2.
|
|
23
|
-
"@internetarchive/modal-manager": "^0.2.
|
|
22
|
+
"@internetarchive/local-cache": "^0.2.1",
|
|
23
|
+
"@internetarchive/modal-manager": "^0.2.8",
|
|
24
24
|
"@internetarchive/shared-resize-observer": "^0.2.0",
|
|
25
|
-
"
|
|
25
|
+
"@internetarchive/toast-manager": "0.1.0",
|
|
26
|
+
"lit": "^2.5.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@open-wc/eslint-config": "^4.2.0",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
},
|
|
55
56
|
"husky": {
|
|
56
57
|
"hooks": {
|
|
58
|
+
"pre-commit": "lint-staged"
|
|
57
59
|
}
|
|
58
60
|
},
|
|
59
61
|
"lint-staged": {
|
|
@@ -100,7 +100,7 @@ export const canBrowseAndBorrow = {
|
|
|
100
100
|
// userid: "",
|
|
101
101
|
bookUrl: '/details/practicalorganic00plim',
|
|
102
102
|
daysLeftOnLoan: 0,
|
|
103
|
-
isAdmin:
|
|
103
|
+
isAdmin: true,
|
|
104
104
|
isArchiveOrgLending: true,
|
|
105
105
|
isAvailable: false,
|
|
106
106
|
isAvailableForBrowsing: false,
|
|
@@ -12,6 +12,7 @@ export default css`
|
|
|
12
12
|
}
|
|
13
13
|
.actiongroup {
|
|
14
14
|
display: flex;
|
|
15
|
+
margin-right: 10px;
|
|
15
16
|
}
|
|
16
17
|
.action-buttons {
|
|
17
18
|
display: inline-flex;
|
|
@@ -33,12 +34,12 @@ export default css`
|
|
|
33
34
|
}
|
|
34
35
|
.primary {
|
|
35
36
|
background-color: ${whiteColor};
|
|
37
|
+
margin-right: 4px;
|
|
36
38
|
}
|
|
37
39
|
.primary,
|
|
38
40
|
.secondary {
|
|
39
41
|
position: relative;
|
|
40
42
|
border-radius: 5px;
|
|
41
|
-
margin: 0 3px;
|
|
42
43
|
}
|
|
43
44
|
.primary .initial {
|
|
44
45
|
border-radius: 4px 0 0 4px;
|
|
@@ -9,6 +9,10 @@ import CollapsibleActionGroupStyle from '../assets/styles/collapsible-action-gro
|
|
|
9
9
|
|
|
10
10
|
import { tabletContainerWidth } from '../core/config/constants.js';
|
|
11
11
|
import { purchaseIcon } from '../assets/data/purchase.js';
|
|
12
|
+
import {
|
|
13
|
+
analyticsCategories,
|
|
14
|
+
analyticsActions,
|
|
15
|
+
} from '../core/config/analytics-event-and-category.js';
|
|
12
16
|
import {
|
|
13
17
|
dropdownOpened,
|
|
14
18
|
dropdownClosed,
|
|
@@ -28,8 +32,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
28
32
|
dropdownArrow: { type: String },
|
|
29
33
|
disabled: { type: Boolean },
|
|
30
34
|
returnUrl: { type: String },
|
|
31
|
-
|
|
32
|
-
autoRenewConfig: { type: Object },
|
|
35
|
+
renewNow: { type: Boolean },
|
|
33
36
|
};
|
|
34
37
|
}
|
|
35
38
|
|
|
@@ -49,8 +52,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
49
52
|
this.loaderIcon = 'https://archive.org/upload/images/tree/loading.gif';
|
|
50
53
|
this.disabled = false;
|
|
51
54
|
this.returnUrl = '';
|
|
52
|
-
this.
|
|
53
|
-
this.autoRenewConfig = {};
|
|
55
|
+
this.renewNow = false;
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
updated(changed) {
|
|
@@ -61,17 +63,28 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
61
63
|
this.resetActions();
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
if (this.
|
|
65
|
-
this.
|
|
66
|
-
new CustomEvent('autoBrowseBook', {
|
|
67
|
-
detail: {
|
|
68
|
-
event: { 'autoRenewed1Hour': 'browseBook' },
|
|
69
|
-
},
|
|
70
|
-
})
|
|
71
|
-
);
|
|
66
|
+
if (changed.has('renewNow') && this.renewNow === true) {
|
|
67
|
+
this.dispatchLoanRenewEvent();
|
|
72
68
|
}
|
|
73
69
|
}
|
|
74
70
|
|
|
71
|
+
// dispatch this event to loan renew handler
|
|
72
|
+
dispatchLoanRenewEvent() {
|
|
73
|
+
const { category, action } = {
|
|
74
|
+
category: analyticsCategories.browse,
|
|
75
|
+
action: analyticsActions.browseLoanRenew,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// listen in action-handler.js to execute ajax call on petabox.
|
|
79
|
+
this.dispatchEvent(
|
|
80
|
+
new CustomEvent('loanRenew', {
|
|
81
|
+
detail: {
|
|
82
|
+
event: { category, action },
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
75
88
|
/**
|
|
76
89
|
* merge primaryActions and secondaryActions into dropdown
|
|
77
90
|
*/
|
|
@@ -43,21 +43,12 @@ export class InfoIcon extends LitElement {
|
|
|
43
43
|
vertical-align: middle;
|
|
44
44
|
--iconFillColor: white;
|
|
45
45
|
}
|
|
46
|
-
.more-info-icon {
|
|
47
|
-
margin-left: 10px;
|
|
48
|
-
}
|
|
49
46
|
.more-info-icon img {
|
|
50
47
|
width: 24px;
|
|
51
48
|
height: 24px;
|
|
52
49
|
vertical-align: middle;
|
|
53
50
|
background: white;
|
|
54
51
|
}
|
|
55
|
-
.more-info-icon.mobile {
|
|
56
|
-
position: absolute;
|
|
57
|
-
top: 4px;
|
|
58
|
-
right: 55px;
|
|
59
|
-
margin-top: 15px;
|
|
60
|
-
}
|
|
61
52
|
.hidden {
|
|
62
53
|
display: none;
|
|
63
54
|
}
|
|
@@ -1,48 +1,83 @@
|
|
|
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() {
|
|
5
6
|
return {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
secondsLeftOnLoan: { type: Number }, // in seconds
|
|
8
|
+
loanTotalTime: { type: Number }, // in seconds
|
|
9
|
+
loanRenewAtLast: { type: Number }, // in seconds
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
constructor() {
|
|
13
14
|
super();
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* seconds left in current loan
|
|
18
|
+
* @type {number}
|
|
19
|
+
*/
|
|
20
|
+
this.secondsLeftOnLoan = 0;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* total seconds a loan does have
|
|
24
|
+
* @type {number}
|
|
25
|
+
*/
|
|
26
|
+
this.loanTotalTime = 0;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* at the remaining time, we attempt to renew current loan
|
|
30
|
+
* @type {number}
|
|
31
|
+
*/
|
|
32
|
+
this.loanRenewAtLast = 0;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* setInterval executed interval
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
16
38
|
this.timerInterval = undefined;
|
|
17
|
-
this.resetTimerCountdown = false;
|
|
18
|
-
}
|
|
19
39
|
|
|
20
|
-
|
|
21
|
-
|
|
40
|
+
/**
|
|
41
|
+
* delay seconds in setInterval function
|
|
42
|
+
* @type {number}
|
|
43
|
+
*/
|
|
44
|
+
this.timerExecutionSeconds = 0;
|
|
22
45
|
}
|
|
23
46
|
|
|
24
|
-
|
|
25
|
-
this.
|
|
47
|
+
disconnectedCallback() {
|
|
48
|
+
clearInterval(this.timerInterval);
|
|
26
49
|
}
|
|
27
50
|
|
|
28
51
|
updated(changed) {
|
|
29
|
-
if (changed.has('
|
|
52
|
+
if (changed.has('secondsLeftOnLoan') && this.secondsLeftOnLoan > 0) {
|
|
30
53
|
clearInterval(this.timerInterval);
|
|
31
|
-
this.timerCountdown()
|
|
54
|
+
this.timerCountdown();
|
|
32
55
|
}
|
|
33
56
|
}
|
|
34
|
-
|
|
57
|
+
|
|
35
58
|
timerCountdown() {
|
|
59
|
+
// Just a QA thing-
|
|
60
|
+
// if `this.loanTotalTime` less then 600 Seconds (10min)
|
|
61
|
+
// - let just execute setInterval in each second
|
|
62
|
+
// - otherwise execute in 60 seconds
|
|
63
|
+
const timerExecutionSeconds = this.loanTotalTime <= 600 ? 1 : 60;
|
|
64
|
+
|
|
36
65
|
this.timerInterval = setInterval(() => {
|
|
37
|
-
this.
|
|
66
|
+
this.secondsLeftOnLoan -= timerExecutionSeconds;
|
|
67
|
+
const secondsLeft = Math.round(this.secondsLeftOnLoan);
|
|
38
68
|
|
|
39
|
-
|
|
40
|
-
|
|
69
|
+
/**
|
|
70
|
+
* execute from last 10th minute to 0th minute
|
|
71
|
+
* - 10th - to check if user has viewed
|
|
72
|
+
* - till 0th - to show warning msg with remaining time to auto expired
|
|
73
|
+
* @see IABookActions::bindLoanRenewEvents
|
|
74
|
+
*/
|
|
75
|
+
if (secondsLeft <= this.loanRenewAtLast) {
|
|
41
76
|
this.dispatchEvent(
|
|
42
|
-
new CustomEvent('
|
|
77
|
+
new CustomEvent('IABookActions:loanRenew', {
|
|
43
78
|
detail: {
|
|
44
|
-
|
|
45
|
-
|
|
79
|
+
hasPageChanged: false,
|
|
80
|
+
secondsLeft,
|
|
46
81
|
},
|
|
47
82
|
bubbles: true,
|
|
48
83
|
composed: true,
|
|
@@ -50,76 +85,100 @@ export default class TimerCountdown extends LitElement {
|
|
|
50
85
|
);
|
|
51
86
|
}
|
|
52
87
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
88
|
+
// clear interval
|
|
89
|
+
if (secondsLeft <= 1) {
|
|
90
|
+
clearInterval(this.timerInterval);
|
|
91
|
+
window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
|
|
92
|
+
}
|
|
93
|
+
}, timerExecutionSeconds * 1000);
|
|
56
94
|
}
|
|
57
95
|
|
|
96
|
+
/**
|
|
97
|
+
* get remaining time with timeunit
|
|
98
|
+
*
|
|
99
|
+
* @memberof TimerCountdown
|
|
100
|
+
* @return string
|
|
101
|
+
*/
|
|
102
|
+
get remainingTime() {
|
|
103
|
+
let unitOfTime = 'second';
|
|
104
|
+
let timeLeft = Math.round(this.secondsLeftOnLoan);
|
|
105
|
+
|
|
106
|
+
if (this.loanTotalTime <= 600) {
|
|
107
|
+
return `${timeLeft} seconds`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (timeLeft > 60) {
|
|
111
|
+
unitOfTime = 'minute';
|
|
112
|
+
timeLeft = Math.floor(timeLeft / 60);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return timeLeft !== 1
|
|
116
|
+
? `${timeLeft} ${unitOfTime}s`
|
|
117
|
+
: `${timeLeft} ${unitOfTime}`;
|
|
118
|
+
}
|
|
58
119
|
|
|
59
120
|
render() {
|
|
60
|
-
return html
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
121
|
+
return html`
|
|
122
|
+
<svg
|
|
123
|
+
width="16"
|
|
124
|
+
height="16"
|
|
125
|
+
viewBox="0 0 100 100"
|
|
126
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
127
|
+
>
|
|
128
|
+
<circle class="circle" cx="50" cy="50" r="50" />
|
|
129
|
+
</svg>
|
|
130
|
+
<span class="sr-only">${this.remainingTime}</span>
|
|
131
|
+
<span>${this.remainingTime}</span>
|
|
132
|
+
`;
|
|
66
133
|
}
|
|
67
134
|
|
|
68
135
|
static get styles() {
|
|
136
|
+
const white = css`var(--white, #fff)`;
|
|
137
|
+
const timerSecondsLeft = css`var(--secondsLeftOnLoan, 6000s)`; //
|
|
138
|
+
const timerStrokeLeft = css`var(--strokeLeftOnLoan, 315)`;
|
|
139
|
+
|
|
69
140
|
return css`
|
|
70
141
|
:host {
|
|
71
142
|
right: 5px;
|
|
72
|
-
font-size: 14px;
|
|
73
|
-
position: absolute;
|
|
74
|
-
}
|
|
75
|
-
#countdown1 {
|
|
76
|
-
position: relative;
|
|
77
|
-
margin: auto;
|
|
78
|
-
margin-top: 100px;
|
|
79
|
-
height: 40px;
|
|
80
|
-
width: 40px;
|
|
81
|
-
text-align: center;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
#countdown-number {
|
|
85
|
-
color: white;
|
|
86
|
-
display: inline-block;
|
|
87
|
-
line-height: 40px;
|
|
88
|
-
margin-right: 12px;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
svg {
|
|
92
143
|
position: absolute;
|
|
93
|
-
top: 0;
|
|
94
|
-
right: 0;
|
|
95
|
-
width: 40px;
|
|
96
|
-
height: 40px;
|
|
97
|
-
transform: rotateY(-180deg) rotateZ(-90deg);
|
|
98
144
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
stroke-width: 3px;
|
|
105
|
-
stroke: white;
|
|
106
|
-
fill: none;
|
|
107
|
-
animation: countdown 60s linear infinite forwards;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
@keyframes countdown {
|
|
111
|
-
from {
|
|
112
|
-
stroke-dashoffset: 0px;
|
|
145
|
+
|
|
146
|
+
@keyframes circletimer {
|
|
147
|
+
0% {
|
|
148
|
+
stroke-dashoffset: ${timerStrokeLeft};
|
|
149
|
+
stroke-dasharray: 315;
|
|
113
150
|
}
|
|
114
|
-
|
|
115
|
-
stroke-dashoffset:
|
|
151
|
+
100% {
|
|
152
|
+
stroke-dashoffset: 0;
|
|
153
|
+
stroke-dasharray: 315;
|
|
116
154
|
}
|
|
117
155
|
}
|
|
118
|
-
|
|
119
|
-
|
|
156
|
+
|
|
157
|
+
svg {
|
|
158
|
+
background-color: ${white};
|
|
159
|
+
border-radius: 50px;
|
|
160
|
+
border: 2px solid ${white};
|
|
161
|
+
transform: rotateZ(-90deg);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
svg .circle {
|
|
165
|
+
stroke: #000;
|
|
166
|
+
stroke-width: 100px;
|
|
167
|
+
fill: ${white};
|
|
168
|
+
stroke-dashoffset: 315;
|
|
169
|
+
stroke-dasharray: 0;
|
|
170
|
+
animation: ${timerSecondsLeft} circletimer linear;
|
|
120
171
|
}
|
|
121
|
-
|
|
122
|
-
|
|
172
|
+
|
|
173
|
+
.sr-only {
|
|
174
|
+
position: absolute;
|
|
175
|
+
left: -9999px;
|
|
176
|
+
width: 1px;
|
|
177
|
+
height: 1px;
|
|
178
|
+
margin: 0;
|
|
179
|
+
padding: 0;
|
|
180
|
+
border: none;
|
|
181
|
+
overflow: hidden;
|
|
123
182
|
}
|
|
124
183
|
`;
|
|
125
184
|
}
|
|
@@ -13,6 +13,7 @@ export const analyticsCategories = {
|
|
|
13
13
|
export const analyticsActions = {
|
|
14
14
|
browse: 'Borrow-1Hour',
|
|
15
15
|
browseAgain: 'Borrow-Again',
|
|
16
|
+
browseLoanRenew: 'Borrow-Loan-Renew',
|
|
16
17
|
borrow: 'Borrow-14Days',
|
|
17
18
|
waitlistJoin: 'JoinWaitlist',
|
|
18
19
|
waitlistLeave: 'LeaveWaitlist',
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sentry logs/messages we send for different actions....
|
|
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
|
+
bookAccessed: 'IABookActions:bookAccessed',
|
|
17
|
+
handleLoanTokenPoller: 'IABookActions:handleLoanTokenPoller',
|
|
18
|
+
setConsecutiveLoanCounts: 'IABookActions:setConsecutiveLoanCounts',
|
|
19
|
+
actionsHandlerService: 'IABookActions:actionsHandlerService',
|
|
20
|
+
};
|
|
@@ -36,7 +36,7 @@ export default class ActionsConfig {
|
|
|
36
36
|
firstBrowseConfig() {
|
|
37
37
|
return {
|
|
38
38
|
id: 'browseBook',
|
|
39
|
-
text: 'Borrow
|
|
39
|
+
text: 'Borrow',
|
|
40
40
|
className: 'primary',
|
|
41
41
|
analyticsEvent: {
|
|
42
42
|
category: this.analyticsCategories.preview,
|
|
@@ -48,7 +48,7 @@ export default class ActionsConfig {
|
|
|
48
48
|
browseAgainConfig() {
|
|
49
49
|
return {
|
|
50
50
|
id: 'browseBookAgain',
|
|
51
|
-
text: 'Borrow
|
|
51
|
+
text: 'Borrow',
|
|
52
52
|
className: 'primary',
|
|
53
53
|
analyticsEvent: {
|
|
54
54
|
category: this.analyticsCategories.browse,
|
|
@@ -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 (
|
|
68
|
-
window?.Sentry?.captureException(
|
|
68
|
+
} catch (error) {
|
|
69
|
+
window?.Sentry?.captureException(
|
|
70
|
+
`${sentryLogs.actionsHandlerService} - Error: ${error}`
|
|
71
|
+
);
|
|
69
72
|
}
|
|
70
73
|
}
|