@internetarchive/ia-book-actions 0.0.29-alpha5 → 0.0.29-alpha50
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 +40 -33
- 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 +118 -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 +321 -139
- 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 -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,20 @@
|
|
|
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
|
-
|
|
133
|
+
|
|
134
|
+
let isDevBox = true;
|
|
135
|
+
iaBookActions.loanRenewTimeConfig = {
|
|
136
|
+
loanTotalTime: isDevBox ? 15 : 3600, // 60 second = 1 min
|
|
137
|
+
loanRenewAtLast: isDevBox ? 10 : 3540, // at last 10th minute
|
|
138
|
+
pageChangedInLast: isDevBox ? 5 : 900, // within last 15 second/minute
|
|
139
|
+
isDevBox: isDevBox,
|
|
134
140
|
};
|
|
135
141
|
|
|
136
142
|
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
137
|
-
let secondsLeftOnLoan = iaBookActions.
|
|
143
|
+
let secondsLeftOnLoan = iaBookActions.loanRenewTimeConfig.loanTotalTime;
|
|
138
144
|
|
|
139
145
|
document.querySelectorAll('.titleBar input[type=checkbox]').forEach((item) => {
|
|
140
146
|
item.addEventListener('click', (e) => {
|
|
@@ -146,21 +152,6 @@
|
|
|
146
152
|
});
|
|
147
153
|
});
|
|
148
154
|
|
|
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
155
|
document.querySelectorAll('.errorEnable input[type=checkbox]').forEach((item) => {
|
|
165
156
|
if (window.location.href.indexOf('?error=true') !== -1) {
|
|
166
157
|
item.checked = true;
|
|
@@ -226,10 +217,10 @@
|
|
|
226
217
|
await localCache.set({
|
|
227
218
|
key: `${identifier}-loanTime`,
|
|
228
219
|
value: new Date(), // current time
|
|
229
|
-
ttl: Number(iaBookActions.
|
|
230
|
-
})
|
|
220
|
+
ttl: Number(iaBookActions.loanRenewTimeConfig.loanTotalTime),
|
|
221
|
+
});
|
|
231
222
|
|
|
232
|
-
await localCache.delete(`${identifier}-
|
|
223
|
+
await localCache.delete(`${identifier}-pageChangedTime`);
|
|
233
224
|
} catch (error) {}
|
|
234
225
|
|
|
235
226
|
} else if(e.target.value === 'browsingExpired') {
|
|
@@ -242,8 +233,11 @@
|
|
|
242
233
|
lendingStatus1.user_has_browsed = false;
|
|
243
234
|
}
|
|
244
235
|
|
|
245
|
-
|
|
246
|
-
|
|
236
|
+
// wait for a while
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
let lending = {...defaultLendingStatus, ...lendingStatus1};
|
|
239
|
+
iaBookActions.lendingStatus = lending;
|
|
240
|
+
}, 10);
|
|
247
241
|
});
|
|
248
242
|
});
|
|
249
243
|
|
|
@@ -292,6 +286,17 @@
|
|
|
292
286
|
iaBookActions.bwbPurchaseUrl = bwbPurchaseUrl;
|
|
293
287
|
})
|
|
294
288
|
});
|
|
289
|
+
|
|
290
|
+
document.querySelector('.pageChangedEvent').addEventListener('click', () => {
|
|
291
|
+
// dispatch event to say book page has flipped
|
|
292
|
+
document.querySelector('ia-book-actions').dispatchEvent(
|
|
293
|
+
new CustomEvent('BookReader:userAction', {
|
|
294
|
+
detail: {},
|
|
295
|
+
bubbles: true,
|
|
296
|
+
composed: true,
|
|
297
|
+
})
|
|
298
|
+
);
|
|
299
|
+
})
|
|
295
300
|
</script>
|
|
296
301
|
|
|
297
302
|
<div>
|
|
@@ -302,6 +307,9 @@
|
|
|
302
307
|
<td class="titleBar">
|
|
303
308
|
<label><input type="checkbox" name="title" value="title" />Title Bar</label>
|
|
304
309
|
</td>
|
|
310
|
+
<td>
|
|
311
|
+
<button class="pageChangedEvent">Page Change Event</button>
|
|
312
|
+
</td>
|
|
305
313
|
</tr>
|
|
306
314
|
</table>
|
|
307
315
|
</fieldset>
|
|
@@ -311,7 +319,6 @@
|
|
|
311
319
|
<table class="initial">
|
|
312
320
|
<tr colspan='5'>
|
|
313
321
|
<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
322
|
</tr>
|
|
316
323
|
<tr>
|
|
317
324
|
<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-alpha50",
|
|
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,68 @@
|
|
|
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
|
+
loanRenewAtLast: { type: Number }, // in seconds
|
|
9
|
+
isDevBox: { type: Boolean },
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
constructor() {
|
|
13
14
|
super();
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* seconds left in current time
|
|
18
|
+
* @type {number}
|
|
19
|
+
*/
|
|
20
|
+
this.secondsLeftOnLoan = 0;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* at the remaining time, we attempt to renew current loan
|
|
24
|
+
* @type {number}
|
|
25
|
+
*/
|
|
26
|
+
this.loanRenewAtLast = 0;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @type {boolean}
|
|
30
|
+
*/
|
|
31
|
+
this.isDevBox = false;
|
|
32
|
+
|
|
33
|
+
// private props
|
|
16
34
|
this.timerInterval = undefined;
|
|
17
|
-
this.resetTimerCountdown = false;
|
|
18
35
|
}
|
|
19
36
|
|
|
20
37
|
disconnectedCallback() {
|
|
21
|
-
clearInterval(this.timerInterval)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
firstUpdated() {
|
|
25
|
-
this.timerCountdown();
|
|
38
|
+
clearInterval(this.timerInterval);
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
updated(changed) {
|
|
29
|
-
if (changed.has('
|
|
42
|
+
if (changed.has('secondsLeftOnLoan') && this.secondsLeftOnLoan > 0) {
|
|
30
43
|
clearInterval(this.timerInterval);
|
|
31
|
-
this.timerCountdown()
|
|
44
|
+
this.timerCountdown();
|
|
32
45
|
}
|
|
33
46
|
}
|
|
34
|
-
|
|
47
|
+
|
|
35
48
|
timerCountdown() {
|
|
49
|
+
// in-case of isDevBox, execute timer in each second instead of 60
|
|
50
|
+
const timerIntervalSeconds = this.isDevBox ? 1 : 60;
|
|
51
|
+
|
|
36
52
|
this.timerInterval = setInterval(() => {
|
|
37
|
-
this.
|
|
53
|
+
// if this.isDevBox, just reduce seconds by 1 instead of 60 (1 min)
|
|
54
|
+
this.secondsLeftOnLoan -= timerIntervalSeconds;
|
|
55
|
+
const secondsLeft = Math.round(this.secondsLeftOnLoan);
|
|
38
56
|
|
|
39
|
-
// execute
|
|
40
|
-
if
|
|
57
|
+
// execute from last 10th minute to 0th minute
|
|
58
|
+
// - 10th - to check if user has viewed
|
|
59
|
+
// - till 0th - to show warning msg with remaining time to auto expired
|
|
60
|
+
if (secondsLeft <= this.loanRenewAtLast) {
|
|
41
61
|
this.dispatchEvent(
|
|
42
|
-
new CustomEvent('
|
|
62
|
+
new CustomEvent('IABookActions:loanRenew', {
|
|
43
63
|
detail: {
|
|
44
|
-
|
|
45
|
-
|
|
64
|
+
hasPageChanged: false,
|
|
65
|
+
secondsLeft,
|
|
46
66
|
},
|
|
47
67
|
bubbles: true,
|
|
48
68
|
composed: true,
|
|
@@ -50,76 +70,100 @@ export default class TimerCountdown extends LitElement {
|
|
|
50
70
|
);
|
|
51
71
|
}
|
|
52
72
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
73
|
+
// clear interval
|
|
74
|
+
if (secondsLeft <= 1) {
|
|
75
|
+
clearInterval(this.timerInterval);
|
|
76
|
+
window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
|
|
77
|
+
}
|
|
78
|
+
}, timerIntervalSeconds * 1000);
|
|
56
79
|
}
|
|
57
80
|
|
|
81
|
+
/**
|
|
82
|
+
* get remaining time with timeunit
|
|
83
|
+
*
|
|
84
|
+
* @memberof TimerCountdown
|
|
85
|
+
* @return string
|
|
86
|
+
*/
|
|
87
|
+
get remainingTime() {
|
|
88
|
+
let unitOfTime = 'second';
|
|
89
|
+
let timeLeft = Math.round(this.secondsLeftOnLoan);
|
|
90
|
+
|
|
91
|
+
if (this.isDevBox) {
|
|
92
|
+
return `${timeLeft} seconds`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (timeLeft > 60) {
|
|
96
|
+
unitOfTime = 'minute';
|
|
97
|
+
timeLeft = Math.floor(timeLeft / 60);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return timeLeft !== 1
|
|
101
|
+
? `${timeLeft} ${unitOfTime}s`
|
|
102
|
+
: `${timeLeft} ${unitOfTime}`;
|
|
103
|
+
}
|
|
58
104
|
|
|
59
105
|
render() {
|
|
60
|
-
return html
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
106
|
+
return html`
|
|
107
|
+
<svg
|
|
108
|
+
width="16"
|
|
109
|
+
height="16"
|
|
110
|
+
viewBox="0 0 100 100"
|
|
111
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
112
|
+
>
|
|
113
|
+
<circle class="circle" cx="50" cy="50" r="50" />
|
|
114
|
+
</svg>
|
|
115
|
+
<span class="sr-only">${this.remainingTime}</span>
|
|
116
|
+
<span>${this.remainingTime}</span>
|
|
117
|
+
`;
|
|
66
118
|
}
|
|
67
119
|
|
|
68
120
|
static get styles() {
|
|
121
|
+
const white = css`var(--white, #fff)`;
|
|
122
|
+
const timerSecondsLeft = css`var(--secondsLeftOnLoan, 6000s)`; //
|
|
123
|
+
const timerStrokeLeft = css`var(--strokeLeftOnLoan, 315)`;
|
|
124
|
+
|
|
69
125
|
return css`
|
|
70
126
|
:host {
|
|
71
127
|
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
128
|
position: absolute;
|
|
93
|
-
top: 0;
|
|
94
|
-
right: 0;
|
|
95
|
-
width: 40px;
|
|
96
|
-
height: 40px;
|
|
97
|
-
transform: rotateY(-180deg) rotateZ(-90deg);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
svg circle {
|
|
101
|
-
stroke-dasharray: 113px;
|
|
102
|
-
stroke-dashoffset: 0px;
|
|
103
|
-
stroke-linecap: round;
|
|
104
|
-
stroke-width: 3px;
|
|
105
|
-
stroke: white;
|
|
106
|
-
fill: none;
|
|
107
|
-
animation: countdown 60s linear infinite forwards;
|
|
108
129
|
}
|
|
109
|
-
|
|
110
|
-
@keyframes
|
|
111
|
-
|
|
112
|
-
stroke-dashoffset:
|
|
130
|
+
|
|
131
|
+
@keyframes circletimer {
|
|
132
|
+
0% {
|
|
133
|
+
stroke-dashoffset: ${timerStrokeLeft};
|
|
134
|
+
stroke-dasharray: 315;
|
|
113
135
|
}
|
|
114
|
-
|
|
115
|
-
stroke-dashoffset:
|
|
136
|
+
100% {
|
|
137
|
+
stroke-dashoffset: 0;
|
|
138
|
+
stroke-dasharray: 315;
|
|
116
139
|
}
|
|
117
140
|
}
|
|
118
|
-
|
|
119
|
-
|
|
141
|
+
|
|
142
|
+
svg {
|
|
143
|
+
background-color: ${white};
|
|
144
|
+
border-radius: 50px;
|
|
145
|
+
border: 2px solid ${white};
|
|
146
|
+
transform: rotateZ(-90deg);
|
|
120
147
|
}
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
|
|
149
|
+
svg .circle {
|
|
150
|
+
stroke: #000;
|
|
151
|
+
stroke-width: 100px;
|
|
152
|
+
fill: ${white};
|
|
153
|
+
stroke-dashoffset: 315;
|
|
154
|
+
stroke-dasharray: 0;
|
|
155
|
+
animation: ${timerSecondsLeft} circletimer linear;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.sr-only {
|
|
159
|
+
position: absolute;
|
|
160
|
+
left: -9999px;
|
|
161
|
+
width: 1px;
|
|
162
|
+
height: 1px;
|
|
163
|
+
margin: 0;
|
|
164
|
+
padding: 0;
|
|
165
|
+
border: none;
|
|
166
|
+
overflow: hidden;
|
|
123
167
|
}
|
|
124
168
|
`;
|
|
125
169
|
}
|
|
@@ -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
|
}
|