@internetarchive/ia-book-actions 0.1.9 → 0.1.10-alpha1
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/package.json +3 -2
- package/src/assets/data/lending-get-status-service.js +2 -2
- package/src/components/collapsible-action-group.js +10 -4
- package/src/components/timer-countdown.js +0 -135
- package/src/core/services/get-lending-actions.js +3 -4
- package/src/core/services/loan-analytics.js +8 -8
- package/src/core/services/loan-renew-helper.js +2 -2
- package/src/ia-book-actions.js +340 -137
- package/test/core/services/loan-renew-helper.test.js +1 -1
- package/test/ia-book-actions.test.js +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10-alpha1",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
"test:watch": "web-test-runner --watch --playwright --browsers chromium firefox webkit"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"@internetarchive/ia-activity-indicator": "^0.0.4",
|
|
21
22
|
"@internetarchive/icon-info": "^1.2.6",
|
|
22
23
|
"@internetarchive/local-cache": "^0.2.1",
|
|
23
|
-
"@internetarchive/modal-manager": "^0.2.
|
|
24
|
+
"@internetarchive/modal-manager": "^0.2.12",
|
|
24
25
|
"@internetarchive/shared-resize-observer": "^0.2.0",
|
|
25
26
|
"@internetarchive/toast-manager": "0.1.0",
|
|
26
27
|
"lit": "^2.5.0"
|
|
@@ -100,7 +100,7 @@ export const canBrowseAndBorrow = {
|
|
|
100
100
|
// userid: "",
|
|
101
101
|
bookUrl: '/details/practicalorganic00plim',
|
|
102
102
|
daysLeftOnLoan: 0,
|
|
103
|
-
isAdmin:
|
|
103
|
+
isAdmin: false,
|
|
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:
|
|
121
|
+
secondsLeftOnLoan: 155,
|
|
122
122
|
shouldProtectImages: true,
|
|
123
123
|
totalWaitlistCount: 0,
|
|
124
124
|
userHasBorrowed: false,
|
|
@@ -30,6 +30,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
30
30
|
returnUrl: { type: String },
|
|
31
31
|
autoRenew: { type: Boolean },
|
|
32
32
|
autoReturn: { type: Boolean },
|
|
33
|
+
returnNow: { type: Boolean },
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -51,6 +52,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
51
52
|
this.returnUrl = '';
|
|
52
53
|
this.autoRenew = false;
|
|
53
54
|
this.autoReturn = false;
|
|
55
|
+
this.returnNow = false;
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
updated(changed) {
|
|
@@ -68,18 +70,22 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
68
70
|
if (changed.has('autoReturn') && this.autoReturn === true) {
|
|
69
71
|
this.dispatchLoanEvent('autoReturn');
|
|
70
72
|
}
|
|
73
|
+
|
|
74
|
+
if (changed.has('returnNow') && this.returnNow === true) {
|
|
75
|
+
this.dispatchLoanEvent('returnNow', { borrowType: 'browse' });
|
|
76
|
+
}
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
/**
|
|
74
|
-
* dispatch event when book is auto renewed / returned
|
|
80
|
+
* dispatch event when book is auto auto-renewed / auto-returned / returned
|
|
75
81
|
* listen these events in action-handler.js to execute ajax call on petabox.
|
|
76
82
|
* @see ActionsHandler
|
|
77
83
|
*
|
|
78
|
-
* @param {string} event - autoRenew|autoReturn
|
|
84
|
+
* @param {string} event - autoRenew|autoReturn|returnNow
|
|
79
85
|
* @memberof CollapsibleActionGroup
|
|
80
86
|
*/
|
|
81
|
-
dispatchLoanEvent(event) {
|
|
82
|
-
this.dispatchEvent(new
|
|
87
|
+
dispatchLoanEvent(event, detail) {
|
|
88
|
+
this.dispatchEvent(new CustomEvent(event, { detail }));
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
/**
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { html, css, LitElement } from 'lit';
|
|
2
|
-
import { sentryLogs } from '../core/config/sentry-events.js';
|
|
3
2
|
|
|
4
3
|
export default class TimerCountdown extends LitElement {
|
|
5
4
|
static get properties() {
|
|
6
5
|
return {
|
|
7
6
|
secondsLeftOnLoan: { type: Number }, // in seconds
|
|
8
|
-
loanTotalTime: { type: Number }, // in seconds
|
|
9
|
-
loanRenewAtLast: { type: Number }, // in seconds
|
|
10
7
|
};
|
|
11
8
|
}
|
|
12
9
|
|
|
@@ -18,138 +15,6 @@ export default class TimerCountdown extends LitElement {
|
|
|
18
15
|
* @type {number}
|
|
19
16
|
*/
|
|
20
17
|
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
|
-
* store time when timer is started
|
|
36
|
-
* @type {string}
|
|
37
|
-
*/
|
|
38
|
-
this.timeWhenTimerStart = '';
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* delay seconds in setInterval function
|
|
42
|
-
* @type {number}
|
|
43
|
-
*/
|
|
44
|
-
this.timerExecutionSeconds = 60;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
disconnectedCallback() {
|
|
48
|
-
window?.IALendingIntervals?.clearTimerCountdown();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
firstUpdated() {
|
|
52
|
-
this.timerCountdown();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
updated(changed) {
|
|
56
|
-
if (changed.has('secondsLeftOnLoan') && this.secondsLeftOnLoan > 0) {
|
|
57
|
-
this.timerCountdown();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
timerCountdown() {
|
|
62
|
-
this.disconnectedCallback();
|
|
63
|
-
|
|
64
|
-
let secondsLeft = this.secondsLeftOnLoan;
|
|
65
|
-
|
|
66
|
-
// store current time
|
|
67
|
-
this.timeWhenTimerStart = new Date();
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* set interval in window object
|
|
71
|
-
* @see ia-lending-intervals.js
|
|
72
|
-
*/
|
|
73
|
-
window.IALendingIntervals.timerCountdown = setInterval(async () => {
|
|
74
|
-
secondsLeft -= this.timerExecutionSeconds;
|
|
75
|
-
secondsLeft = Math.round(secondsLeft); // round number
|
|
76
|
-
|
|
77
|
-
// re-sync timer if gone off because of background window
|
|
78
|
-
await this.reSyncTimerIfGoneOff(secondsLeft);
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* execute from last 10th minute to 0th minute
|
|
82
|
-
* - 10th - to check if user has viewed
|
|
83
|
-
* - till 0th - to show warning msg with remaining time to auto expired
|
|
84
|
-
* @see IABookActions::bindLoanRenewEvents
|
|
85
|
-
*/
|
|
86
|
-
if (secondsLeft <= this.loanRenewAtLast) {
|
|
87
|
-
this.dispatchLoanRenewEvent(secondsLeft);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// clear interval in secondsLeft if less
|
|
91
|
-
if (secondsLeft <= this.timerExecutionSeconds) {
|
|
92
|
-
this.disconnectedCallback();
|
|
93
|
-
window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
|
|
94
|
-
}
|
|
95
|
-
}, this.timerExecutionSeconds * 1000);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* dispatch loan renew attempt event
|
|
100
|
-
*
|
|
101
|
-
* @param {number} secondsLeft
|
|
102
|
-
* @memberof TimerCountdown
|
|
103
|
-
*/
|
|
104
|
-
dispatchLoanRenewEvent(secondsLeft) {
|
|
105
|
-
this.dispatchEvent(
|
|
106
|
-
new CustomEvent('IABookActions:loanRenew', {
|
|
107
|
-
detail: {
|
|
108
|
-
hasPageChanged: false,
|
|
109
|
-
secondsLeft,
|
|
110
|
-
},
|
|
111
|
-
bubbles: true,
|
|
112
|
-
composed: true,
|
|
113
|
-
})
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* helper function to determine if timer is not in sync properly
|
|
119
|
-
*
|
|
120
|
-
* @param {number} timerSecondsLeft - actual seconds left get from setInterval
|
|
121
|
-
*
|
|
122
|
-
* @memberof TimerCountdown
|
|
123
|
-
*/
|
|
124
|
-
async reSyncTimerIfGoneOff(timerSecondsLeft) {
|
|
125
|
-
// debug info
|
|
126
|
-
console.log(
|
|
127
|
-
new Date().toLocaleTimeString(),
|
|
128
|
-
'timeLeftInSec',
|
|
129
|
-
timerSecondsLeft,
|
|
130
|
-
' ||| timeLeftInMin',
|
|
131
|
-
Math.ceil(timerSecondsLeft / 60)
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
const currentTime = new Date();
|
|
135
|
-
|
|
136
|
-
// current time - loan time
|
|
137
|
-
const diffInSeconds =
|
|
138
|
-
currentTime.getTime() / 1000 - this.timeWhenTimerStart.getTime() / 1000;
|
|
139
|
-
|
|
140
|
-
const secondsShouldLeft = this.secondsLeftOnLoan - diffInSeconds;
|
|
141
|
-
|
|
142
|
-
// convert in minutes
|
|
143
|
-
const whatIsleft = Math.round(timerSecondsLeft);
|
|
144
|
-
const whatShouldLeft = Math.round(secondsShouldLeft);
|
|
145
|
-
|
|
146
|
-
if (whatIsleft !== whatShouldLeft) {
|
|
147
|
-
// debug info
|
|
148
|
-
console.log(
|
|
149
|
-
`timer is gone off, let's re-sync, whatIsleft -> ${whatIsleft}, whatShouldLeft -> ${whatShouldLeft}`
|
|
150
|
-
);
|
|
151
|
-
this.secondsLeftOnLoan = secondsShouldLeft; // the seconds should left in timer again
|
|
152
|
-
}
|
|
153
18
|
}
|
|
154
19
|
|
|
155
20
|
/**
|
|
@@ -40,7 +40,7 @@ import ActionsConfig from './actions-config.js';
|
|
|
40
40
|
* @enum {string}
|
|
41
41
|
*/
|
|
42
42
|
export const bookTitles = {
|
|
43
|
-
available_1hr: 'Renews
|
|
43
|
+
available_1hr: 'Renews automatically as long as pages are turned.',
|
|
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: 'Renews automatically as long as pages are turned.',
|
|
53
53
|
unavailable: 'This book is not available at this time.',
|
|
54
54
|
};
|
|
55
55
|
|
|
@@ -98,8 +98,7 @@ export class GetLendingActions {
|
|
|
98
98
|
let isBrowsing =
|
|
99
99
|
lendingStatus.user_has_browsed && !lendingStatus.browsingExpired;
|
|
100
100
|
if (isBrowsing) {
|
|
101
|
-
primaryTitleText =
|
|
102
|
-
'Returns automatically after 25 minutes of inactivity.';
|
|
101
|
+
primaryTitleText = bookTitles.available_1hr;
|
|
103
102
|
} else {
|
|
104
103
|
primaryTitleText = `Your loan of this book has ${lendingStatus.daysLeftOnLoan} days left.`;
|
|
105
104
|
}
|
|
@@ -144,14 +144,14 @@ export default class LoanAnanlytics {
|
|
|
144
144
|
* @memberof LoanAnanlytics
|
|
145
145
|
*/
|
|
146
146
|
sendEvent(eventCategory, eventAction, label, extraParams) {
|
|
147
|
-
console.log(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
);
|
|
147
|
+
// console.log(
|
|
148
|
+
// 'eventCategory:-',
|
|
149
|
+
// eventCategory,
|
|
150
|
+
// '\t||\teventAction:-',
|
|
151
|
+
// eventAction,
|
|
152
|
+
// '\t||\tlabel:-',
|
|
153
|
+
// label
|
|
154
|
+
// );
|
|
155
155
|
|
|
156
156
|
window?.archive_analytics?.send_event_no_sampling(
|
|
157
157
|
eventCategory,
|
|
@@ -16,7 +16,7 @@ export class LoanRenewHelper {
|
|
|
16
16
|
this.loanRenewMessage =
|
|
17
17
|
'This book has been renewed for #time #unitsOfTime.';
|
|
18
18
|
this.loanReturnWarning =
|
|
19
|
-
'
|
|
19
|
+
'With no action, this book will be auto-returned in #time #unitsOfTime.';
|
|
20
20
|
|
|
21
21
|
// private props
|
|
22
22
|
this.result = {
|
|
@@ -39,7 +39,7 @@ export class LoanRenewHelper {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Trigger this function when user has browsed a book and change the
|
|
42
|
+
* Trigger this function when user has browsed a book and change the page
|
|
43
43
|
* - every time user change the page, we set current time in indexedDB
|
|
44
44
|
* - also check if need to auto renew current loan
|
|
45
45
|
*
|
package/src/ia-book-actions.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable camelcase */
|
|
2
|
+
/* eslint-disable class-methods-use-this */
|
|
2
3
|
import { html, css, LitElement, nothing } from 'lit';
|
|
3
4
|
|
|
4
5
|
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
|
@@ -23,6 +24,21 @@ export const events = {
|
|
|
23
24
|
browseExpired: 'IABookReader:BrowsingHasExpired',
|
|
24
25
|
};
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* custom styling for modal-manager buttons
|
|
29
|
+
* TODO: lets allow modal-manager to know ia-button classes
|
|
30
|
+
*/
|
|
31
|
+
export const modalButtonStyle = {
|
|
32
|
+
iaButton:
|
|
33
|
+
'min-height:3.5rem;cursor:pointer;color:white;border-radius:0.4rem;border:1px solid #c5d1df;padding:4px 8px;width:auto;user-select:none;',
|
|
34
|
+
renew: 'background:#194880;width:110px;',
|
|
35
|
+
return: 'background:#d9534f;width:120px;',
|
|
36
|
+
loaderIcon:
|
|
37
|
+
'display:inline-block;width:20px;height:20px;margin-top:2px;color:white;--activityIndicatorLoadingRingColor:#fff;--activityIndicatorLoadingDotColor:#fff;',
|
|
38
|
+
refresh:
|
|
39
|
+
'background:none;font-size:inherit;border:0;padding:0;color:#0000ee;cursor:pointer;text-decoration:underline',
|
|
40
|
+
};
|
|
41
|
+
|
|
26
42
|
export default class IABookActions extends LitElement {
|
|
27
43
|
static get properties() {
|
|
28
44
|
return {
|
|
@@ -70,11 +86,17 @@ export default class IABookActions extends LitElement {
|
|
|
70
86
|
this.primaryColor = 'primary';
|
|
71
87
|
this.secondaryActions = [];
|
|
72
88
|
this.lendingOptions = {};
|
|
73
|
-
this.borrowType =
|
|
74
|
-
this.consecutiveLoanCounts = 1; // consecutive loan count
|
|
75
|
-
this.suppressToast = false;
|
|
76
|
-
this.suppressAutoRenew = false;
|
|
89
|
+
this.borrowType = null; // (browsed|borrowed)
|
|
77
90
|
this.browseTimer = undefined;
|
|
91
|
+
this.timerExecutionSeconds = 30;
|
|
92
|
+
|
|
93
|
+
/** @deprecated */
|
|
94
|
+
this.toast = undefined;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* when user click on [return the book] button on warning modal
|
|
98
|
+
*/
|
|
99
|
+
this.returnNow = false;
|
|
78
100
|
|
|
79
101
|
/**
|
|
80
102
|
* contains one hour auto-loan-renew time configuration
|
|
@@ -171,9 +193,6 @@ export default class IABookActions extends LitElement {
|
|
|
171
193
|
/** End SharedObserver resize handler */
|
|
172
194
|
|
|
173
195
|
async setupLendingToolbarActions() {
|
|
174
|
-
this.suppressToast = false;
|
|
175
|
-
this.suppressAutoRenew = false;
|
|
176
|
-
|
|
177
196
|
this.lendingOptions = new GetLendingActions(
|
|
178
197
|
this.userid,
|
|
179
198
|
this.identifier,
|
|
@@ -193,7 +212,7 @@ export default class IABookActions extends LitElement {
|
|
|
193
212
|
return action != null;
|
|
194
213
|
});
|
|
195
214
|
|
|
196
|
-
this.borrowType = actions.borrowType;
|
|
215
|
+
this.borrowType = actions.borrowType ? actions.borrowType : null;
|
|
197
216
|
|
|
198
217
|
const hasExpired =
|
|
199
218
|
'browsingExpired' in this.lendingStatus &&
|
|
@@ -218,8 +237,11 @@ export default class IABookActions extends LitElement {
|
|
|
218
237
|
}
|
|
219
238
|
|
|
220
239
|
if (this.borrowType === 'browsed') {
|
|
240
|
+
// start timer for loan-renew
|
|
241
|
+
await this.startTimerCountdown();
|
|
242
|
+
|
|
221
243
|
// start timer for browsed.
|
|
222
|
-
this.startBrowseTimer();
|
|
244
|
+
await this.startBrowseTimer();
|
|
223
245
|
}
|
|
224
246
|
|
|
225
247
|
// early return if not borrowed or no action-bar
|
|
@@ -248,84 +270,17 @@ export default class IABookActions extends LitElement {
|
|
|
248
270
|
* Bind 1 hour loan auto renew event,
|
|
249
271
|
* There are two events we want to use,
|
|
250
272
|
* 1. BookReader:userAction - dispatched from bookreader side
|
|
251
|
-
* 2.
|
|
252
|
-
* 3. IABookActions:loanRenew - dispatched from timer-countdown component
|
|
273
|
+
* 2. IABookActions:loanRenew - dispatched from timer-countdown component
|
|
253
274
|
*/
|
|
254
275
|
bindLoanRenewEvents() {
|
|
255
276
|
/**
|
|
256
277
|
* dispatched this event from bookreader page changed
|
|
257
278
|
*/
|
|
258
279
|
window.addEventListener('BookReader:userAction', () => {
|
|
259
|
-
console.log('** BR user Action', {
|
|
260
|
-
suppressAutoRenew: this.suppressAutoRenew,
|
|
261
|
-
borrowType: this.borrowType,
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
this.suppressToast = true;
|
|
265
|
-
this.closeToastManager();
|
|
266
|
-
|
|
267
|
-
if (this.suppressAutoRenew) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
280
|
if (this.borrowType === 'browsed') {
|
|
272
281
|
this.autoLoanRenewChecker(true);
|
|
273
282
|
}
|
|
274
283
|
});
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* detect click-event on document to close toast-template
|
|
278
|
-
*/
|
|
279
|
-
document.addEventListener('click', e => {
|
|
280
|
-
console.log('*** top level click handler to remove toast on click');
|
|
281
|
-
if (this.loanRenewHelper && this.loanRenewResult.secondsLeft > 0) {
|
|
282
|
-
this.suppressToast = true;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// reload when user click on book-page and book is EXPIRED
|
|
286
|
-
const hasExpired =
|
|
287
|
-
'browsingExpired' in this.lendingStatus &&
|
|
288
|
-
this.lendingStatus?.browsingExpired;
|
|
289
|
-
if (hasExpired && e.target.nodeName !== 'IA-BOOK-ACTIONS') {
|
|
290
|
-
window.location?.reload();
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* this event dispatched from timer-countdown component for:
|
|
296
|
-
* 1. user turned book page after showing auto-returned warning message
|
|
297
|
-
* 2. show warning message having remaining time
|
|
298
|
-
* @see TimerCountdown::timerCountdown
|
|
299
|
-
*/
|
|
300
|
-
this.addEventListener('IABookActions:loanRenew', async event => {
|
|
301
|
-
console.log('** IABookActions:loanRenew', event.detail);
|
|
302
|
-
await this.autoLoanRenewChecker(false);
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* auto-renew is not possible in last seconds (let say 50 second) because,
|
|
306
|
-
* 1. less time to execute ajax call
|
|
307
|
-
* 2. less time to write loan on datanodes
|
|
308
|
-
* 3. less time to load images by create_token api
|
|
309
|
-
* so if seconds left is < 50, just expire the loan
|
|
310
|
-
*/
|
|
311
|
-
let secondsLeft = event?.detail?.secondsLeft;
|
|
312
|
-
if (secondsLeft < 50) {
|
|
313
|
-
this.suppressAutoRenew = true;
|
|
314
|
-
this.browseHasExpired();
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// show warning message with remaining time to auto returned it.
|
|
318
|
-
if (this.loanRenewResult.renewNow === false) {
|
|
319
|
-
/**
|
|
320
|
-
* so compensate for the 50 second buffer to handle above race conditions
|
|
321
|
-
* let's reduce 1 min from warning texts and early return the book when 1 min left.
|
|
322
|
-
*/
|
|
323
|
-
secondsLeft -= 60;
|
|
324
|
-
|
|
325
|
-
this.loanRenewResult.secondsLeft = secondsLeft;
|
|
326
|
-
this.showToastMessage();
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
284
|
}
|
|
330
285
|
|
|
331
286
|
/**
|
|
@@ -347,34 +302,161 @@ export default class IABookActions extends LitElement {
|
|
|
347
302
|
}
|
|
348
303
|
|
|
349
304
|
/**
|
|
305
|
+
* create / select the modal-manager component on DOM
|
|
306
|
+
* @memberof IABookActions
|
|
307
|
+
*/
|
|
308
|
+
async useModalManager() {
|
|
309
|
+
if (!this.modal) {
|
|
310
|
+
this.modal = document.querySelector('modal-manager');
|
|
311
|
+
|
|
312
|
+
if (!this.modal) this.modal = document.createElement('modal-manager');
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
this.modal.id = 'action-bar-modal';
|
|
316
|
+
await document.body.appendChild(this.modal);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Show the waring modal to ask user if they are still reading
|
|
321
|
+
*/
|
|
322
|
+
async showWarningModal() {
|
|
323
|
+
console.log('****** showWarningModal ******');
|
|
324
|
+
await this.useModalManager();
|
|
325
|
+
|
|
326
|
+
// if secondsLeft < 60, consider it 1 minute
|
|
327
|
+
let { secondsLeft } = this.loanRenewResult;
|
|
328
|
+
if (secondsLeft === undefined) {
|
|
329
|
+
secondsLeft = this.lendingStatus.secondsLeftOnLoan;
|
|
330
|
+
} else {
|
|
331
|
+
secondsLeft = secondsLeft > 60 ? secondsLeft : 60;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const config = new ModalConfig();
|
|
335
|
+
config.headline = 'Are you still here?';
|
|
336
|
+
config.showCloseButton = false;
|
|
337
|
+
config.closeOnBackdropClick = false;
|
|
338
|
+
config.message = this.loanRenewHelper?.getMessageTexts(
|
|
339
|
+
this.loanRenewResult.texts,
|
|
340
|
+
secondsLeft
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
const customContent = html`<br />
|
|
344
|
+
<div id="custom-buttons" style="display:flex;justify-content:center;">
|
|
345
|
+
<button
|
|
346
|
+
style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
|
|
347
|
+
@click=${async event => {
|
|
348
|
+
await this.changeModalState(event);
|
|
349
|
+
this.loanRenewResult = { texts: '', renewNow: true };
|
|
350
|
+
}}
|
|
351
|
+
>
|
|
352
|
+
Keep reading
|
|
353
|
+
</button>
|
|
354
|
+
<button
|
|
355
|
+
style="${modalButtonStyle.iaButton} ${modalButtonStyle.return}"
|
|
356
|
+
@click=${event => {
|
|
357
|
+
this.changeModalState(event);
|
|
358
|
+
document.querySelector('ia-book-actions').disableActionGroup = true;
|
|
359
|
+
this.returnNow = true;
|
|
360
|
+
}}
|
|
361
|
+
>
|
|
362
|
+
Return the book
|
|
363
|
+
</button>
|
|
364
|
+
</div> `;
|
|
365
|
+
|
|
366
|
+
this.modal?.showModal({ config, customModalContent: customContent });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* helper function to change button click states on modal-manager
|
|
371
|
+
* - add loader on button click
|
|
372
|
+
* - change button appearance
|
|
373
|
+
*
|
|
374
|
+
* @param {Event} event
|
|
375
|
+
*/
|
|
376
|
+
changeModalState(event) {
|
|
377
|
+
if (event.target === undefined) return;
|
|
378
|
+
|
|
379
|
+
const button = event.target;
|
|
380
|
+
button.innerHTML = `<ia-activity-indicator
|
|
381
|
+
mode="processing"
|
|
382
|
+
style=${modalButtonStyle.loaderIcon}
|
|
383
|
+
></ia-activity-indicator>`;
|
|
384
|
+
|
|
385
|
+
const parentElement = event.target.parentNode;
|
|
386
|
+
parentElement.style.pointerEvents = 'none';
|
|
387
|
+
parentElement.style.opacity = 0.8;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Show modal when book is auto returned
|
|
392
|
+
*/
|
|
393
|
+
async showExpiredModal() {
|
|
394
|
+
console.log('showExpiredModal()');
|
|
395
|
+
await this.useModalManager();
|
|
396
|
+
|
|
397
|
+
const config = new ModalConfig();
|
|
398
|
+
config.headline = '';
|
|
399
|
+
config.showCloseButton = false;
|
|
400
|
+
config.closeOnBackdropClick = false;
|
|
401
|
+
config.message = 'This book has been returned due to inactivity.';
|
|
402
|
+
|
|
403
|
+
const customContent = html`<br />
|
|
404
|
+
<div style="text-align: center">
|
|
405
|
+
<button
|
|
406
|
+
style="${modalButtonStyle.iaButton} ${modalButtonStyle.renew}"
|
|
407
|
+
@click=${() => {
|
|
408
|
+
window.location?.reload();
|
|
409
|
+
}}
|
|
410
|
+
>
|
|
411
|
+
Okay
|
|
412
|
+
</button>
|
|
413
|
+
</div> `;
|
|
414
|
+
|
|
415
|
+
this.modal?.showModal({ config, customModalContent: customContent });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* close/hide modal-manager
|
|
420
|
+
*/
|
|
421
|
+
async closeModalManager() {
|
|
422
|
+
this.modal = document.querySelector('modal-manager');
|
|
423
|
+
this.modal?.closeModal();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* @deprecated
|
|
428
|
+
* create / select the toast-template component on DOM
|
|
429
|
+
*
|
|
430
|
+
* @memberof IABookActions
|
|
431
|
+
*/
|
|
432
|
+
async useToastManager() {
|
|
433
|
+
if (!this.toast) {
|
|
434
|
+
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
435
|
+
|
|
436
|
+
if (!this.toast) this.toast = document.createElement('toast-template');
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
await this.shadowRoot.appendChild(this.toast);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @deprecated
|
|
350
444
|
* close/hide toast message
|
|
351
445
|
*/
|
|
352
446
|
async closeToastManager() {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if (toastTemplate) {
|
|
356
|
-
toastTemplate?.remove();
|
|
357
|
-
}
|
|
447
|
+
this.toast = this.shadowRoot.querySelector('toast-template');
|
|
448
|
+
this.toast?.remove();
|
|
358
449
|
}
|
|
359
450
|
|
|
360
451
|
/**
|
|
452
|
+
* @deprecated
|
|
361
453
|
* Show toast messages on some specific loan renew features. e.g.
|
|
362
454
|
* - show message when book is auto renewed
|
|
363
455
|
* - show message when book is expired
|
|
364
456
|
* - show message having remaining time when book is about to auto returned
|
|
365
457
|
*/
|
|
366
458
|
async showToastMessage() {
|
|
367
|
-
|
|
368
|
-
suppressToast: this.suppressToast,
|
|
369
|
-
loanRenewResult: this.loanRenewResult,
|
|
370
|
-
});
|
|
371
|
-
if (this.suppressToast) return;
|
|
372
|
-
|
|
373
|
-
let toastTemplate = this.shadowRoot.querySelector('toast-template');
|
|
374
|
-
if (!toastTemplate) {
|
|
375
|
-
toastTemplate = document.createElement('toast-template');
|
|
376
|
-
}
|
|
377
|
-
await this.shadowRoot.appendChild(toastTemplate);
|
|
459
|
+
await this.useToastManager();
|
|
378
460
|
|
|
379
461
|
// if secondsLeft < 60, consider it 1 minute
|
|
380
462
|
let { secondsLeft } = this.loanRenewResult;
|
|
@@ -391,12 +473,14 @@ export default class IABookActions extends LitElement {
|
|
|
391
473
|
secondsLeft
|
|
392
474
|
);
|
|
393
475
|
|
|
394
|
-
|
|
476
|
+
this.toast?.showToast({
|
|
395
477
|
config,
|
|
396
478
|
});
|
|
397
479
|
}
|
|
398
480
|
|
|
399
481
|
async browseHasRenew() {
|
|
482
|
+
window?.IALendingIntervals?.clearAll();
|
|
483
|
+
|
|
400
484
|
const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
|
|
401
485
|
const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
|
|
402
486
|
|
|
@@ -407,24 +491,6 @@ export default class IABookActions extends LitElement {
|
|
|
407
491
|
secondsLeftOnLoan: secondsLeft,
|
|
408
492
|
};
|
|
409
493
|
this.lendingStatus = currStatus;
|
|
410
|
-
|
|
411
|
-
this.startBrowseTimer();
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
startBrowseTimer() {
|
|
415
|
-
clearTimeout(this.browseTimer);
|
|
416
|
-
const {
|
|
417
|
-
browsingExpired,
|
|
418
|
-
user_has_browsed,
|
|
419
|
-
secondsLeftOnLoan,
|
|
420
|
-
} = this.lendingStatus;
|
|
421
|
-
if (!user_has_browsed || browsingExpired) {
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
this.browseTimer = setTimeout(() => {
|
|
426
|
-
this.browseHasExpired();
|
|
427
|
-
}, secondsLeftOnLoan * 1000);
|
|
428
494
|
}
|
|
429
495
|
|
|
430
496
|
/**
|
|
@@ -443,14 +509,31 @@ export default class IABookActions extends LitElement {
|
|
|
443
509
|
// show message after browsed book is expired.
|
|
444
510
|
this.loanRenewResult.renewNow = false;
|
|
445
511
|
this.loanRenewResult.texts =
|
|
446
|
-
'This book has been
|
|
512
|
+
'This book has been returned due to inactivity.';
|
|
447
513
|
|
|
448
|
-
this.
|
|
449
|
-
this.showToastMessage();
|
|
514
|
+
await this.showExpiredModal();
|
|
450
515
|
|
|
451
516
|
window?.Sentry?.captureMessage(sentryLogs.browseHasExpired);
|
|
452
517
|
}
|
|
453
518
|
|
|
519
|
+
async startBrowseTimer() {
|
|
520
|
+
clearTimeout(this.browseTimer);
|
|
521
|
+
|
|
522
|
+
const {
|
|
523
|
+
browsingExpired,
|
|
524
|
+
user_has_browsed,
|
|
525
|
+
secondsLeftOnLoan,
|
|
526
|
+
} = this.lendingStatus;
|
|
527
|
+
if (!user_has_browsed || browsingExpired) {
|
|
528
|
+
console.log('user not browsed', this.lendingStatus);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
this.browseTimer = setTimeout(() => {
|
|
533
|
+
this.browseHasExpired();
|
|
534
|
+
}, secondsLeftOnLoan * 1000);
|
|
535
|
+
}
|
|
536
|
+
|
|
454
537
|
/**
|
|
455
538
|
* Reset timer animation state after book renewed
|
|
456
539
|
*/
|
|
@@ -501,8 +584,6 @@ export default class IABookActions extends LitElement {
|
|
|
501
584
|
return this.borrowType === 'browsed'
|
|
502
585
|
? html`<timer-countdown
|
|
503
586
|
.secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
|
|
504
|
-
.loanTotalTime=${this.loanRenewTimeConfig.loanTotalTime}
|
|
505
|
-
.loanRenewAtLast=${this.loanRenewTimeConfig.loanRenewAtLast}
|
|
506
587
|
></timer-countdown>`
|
|
507
588
|
: nothing;
|
|
508
589
|
}
|
|
@@ -524,6 +605,7 @@ export default class IABookActions extends LitElement {
|
|
|
524
605
|
?disabled=${this.disableActionGroup}
|
|
525
606
|
?autoRenew=${this.loanRenewResult.renewNow}
|
|
526
607
|
?autoReturn=${this.lendingStatus.browsingExpired}
|
|
608
|
+
?returnNow=${this.returnNow}
|
|
527
609
|
@loanAutoRenewed=${this.handleLoanAutoRenewed}
|
|
528
610
|
@lendingActionError=${this.handleLendingActionError}
|
|
529
611
|
@toggleActionGroup=${this.handleToggleActionGroup}
|
|
@@ -545,19 +627,149 @@ export default class IABookActions extends LitElement {
|
|
|
545
627
|
if (this.loanRenewResult.renewNow) {
|
|
546
628
|
window?.IALendingIntervals?.clearAll();
|
|
547
629
|
|
|
548
|
-
this.suppressToast = false;
|
|
549
|
-
await this.browseHasRenew();
|
|
550
|
-
await this.showToastMessage();
|
|
551
|
-
await this.resetTimerCountState();
|
|
552
|
-
|
|
553
|
-
window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
|
|
554
|
-
|
|
555
630
|
// testing console....
|
|
556
631
|
console.log('IABookActions: AutoRenewed:- ', {
|
|
557
632
|
ajaxResponse: event?.detail?.data,
|
|
558
633
|
loanRenewResult: this.loanRenewResult,
|
|
559
634
|
secondsLeftOnLoan: Math.round(this.lendingStatus.secondsLeftOnLoan),
|
|
560
635
|
});
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* update the lendingStatus property
|
|
639
|
+
*/
|
|
640
|
+
await this.browseHasRenew();
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* reset timer countdown states
|
|
644
|
+
*/
|
|
645
|
+
await this.resetTimerCountState();
|
|
646
|
+
|
|
647
|
+
// close the modal
|
|
648
|
+
this.modal?.remove();
|
|
649
|
+
this.modal?.showModal({ config: {}, customModalContent: `` });
|
|
650
|
+
|
|
651
|
+
window?.Sentry?.captureMessage(sentryLogs.bookHasRenewed);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* start timer countdown interval after loan auto-renewed
|
|
657
|
+
*
|
|
658
|
+
* @memberof IABookActions
|
|
659
|
+
*/
|
|
660
|
+
startTimerCountdown() {
|
|
661
|
+
console.log('startTimerCountdown()');
|
|
662
|
+
window?.IALendingIntervals?.clearTimerCountdown();
|
|
663
|
+
|
|
664
|
+
let secondsLeft = Number(this.lendingStatus.secondsLeftOnLoan);
|
|
665
|
+
this.timeWhenTimerStart = new Date();
|
|
666
|
+
|
|
667
|
+
window.IALendingIntervals.timerCountdown = setInterval(async () => {
|
|
668
|
+
secondsLeft -= this.timerExecutionSeconds;
|
|
669
|
+
secondsLeft = Math.round(secondsLeft); // round number
|
|
670
|
+
|
|
671
|
+
// re-sync timer if gone off because of background window
|
|
672
|
+
await this.reSyncTimerIfGoneOff(secondsLeft);
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* execute from last 10th minute to 0th minute
|
|
676
|
+
* - 10th - to check if user has viewed
|
|
677
|
+
* - till 0th - to show warning msg with remaining time to auto expired
|
|
678
|
+
* @see IABookActions::bindLoanRenewEvents
|
|
679
|
+
*/
|
|
680
|
+
if (secondsLeft <= this.loanRenewTimeConfig.loanRenewAtLast) {
|
|
681
|
+
await this.loanRenewAttempt(secondsLeft);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// clear interval in secondsLeft if less
|
|
685
|
+
if (secondsLeft <= this.timerExecutionSeconds) {
|
|
686
|
+
this.disconnectedCallback();
|
|
687
|
+
window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
|
|
688
|
+
}
|
|
689
|
+
}, this.timerExecutionSeconds * 1000);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* helper function to determine if timer is not in sync properly
|
|
694
|
+
*
|
|
695
|
+
* @param {number} timerSecondsLeft - actual seconds left get from setInterval
|
|
696
|
+
*
|
|
697
|
+
* @memberof TimerCountdown
|
|
698
|
+
*/
|
|
699
|
+
async reSyncTimerIfGoneOff(timerSecondsLeft) {
|
|
700
|
+
// debug info
|
|
701
|
+
console.log(
|
|
702
|
+
new Date().toLocaleTimeString(),
|
|
703
|
+
'timeLeftInSec',
|
|
704
|
+
timerSecondsLeft,
|
|
705
|
+
' ||| timeLeftInMin',
|
|
706
|
+
Math.ceil(timerSecondsLeft / 60)
|
|
707
|
+
);
|
|
708
|
+
|
|
709
|
+
const currentTime = new Date();
|
|
710
|
+
|
|
711
|
+
// current time - loan time
|
|
712
|
+
const diffInSeconds =
|
|
713
|
+
currentTime.getTime() / 1000 - this.timeWhenTimerStart.getTime() / 1000;
|
|
714
|
+
|
|
715
|
+
const secondsShouldLeft =
|
|
716
|
+
this.lendingStatus.secondsLeftOnLoan - diffInSeconds;
|
|
717
|
+
|
|
718
|
+
// convert in minutes
|
|
719
|
+
const whatIsleft = Math.round(timerSecondsLeft);
|
|
720
|
+
const whatShouldLeft = Math.round(secondsShouldLeft);
|
|
721
|
+
|
|
722
|
+
if (whatIsleft !== whatShouldLeft) {
|
|
723
|
+
// debug info
|
|
724
|
+
console.log(
|
|
725
|
+
`timer is gone off, let's re-sync, whatIsleft -> ${whatIsleft}, whatShouldLeft -> ${whatShouldLeft}`
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
// the seconds should left in timer again
|
|
729
|
+
const currStatus = {
|
|
730
|
+
...this.lendingStatus,
|
|
731
|
+
secondsLeftOnLoan: secondsShouldLeft,
|
|
732
|
+
};
|
|
733
|
+
this.lendingStatus = currStatus;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* attmept to loan renew from
|
|
739
|
+
* - timer countdown
|
|
740
|
+
* - onclick on [keep reading] button
|
|
741
|
+
*
|
|
742
|
+
* @param {*} secondsLeft
|
|
743
|
+
* @memberof IABookActions
|
|
744
|
+
*/
|
|
745
|
+
async loanRenewAttempt(secondsLeft) {
|
|
746
|
+
console.log('loanRenewAttempt()');
|
|
747
|
+
let loanSecondsLeft = secondsLeft;
|
|
748
|
+
/**
|
|
749
|
+
* auto-renew is not possible in last seconds (let say 50 second) because,
|
|
750
|
+
* 1. less time to execute ajax call
|
|
751
|
+
* 2. less time to write loan on datanodes
|
|
752
|
+
* 3. less time to load images by create_token api
|
|
753
|
+
* so if seconds left is < 50, just expire the loan
|
|
754
|
+
*/
|
|
755
|
+
if (loanSecondsLeft < 50) {
|
|
756
|
+
console.log('if (loanSecondsLeft < 50) {');
|
|
757
|
+
await this.browseHasExpired();
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
await this.autoLoanRenewChecker(false);
|
|
762
|
+
|
|
763
|
+
// show warning modal with remaining time to auto returned it.
|
|
764
|
+
if (this.loanRenewResult.renewNow === false) {
|
|
765
|
+
/**
|
|
766
|
+
* so compensate for the 50 second buffer to handle above race conditions
|
|
767
|
+
* let's reduce 1 min from warning texts and early return the book when 1 min left.
|
|
768
|
+
*/
|
|
769
|
+
loanSecondsLeft -= 60;
|
|
770
|
+
this.loanRenewResult.secondsLeft = loanSecondsLeft;
|
|
771
|
+
|
|
772
|
+
this.showWarningModal();
|
|
561
773
|
}
|
|
562
774
|
}
|
|
563
775
|
|
|
@@ -602,7 +814,7 @@ export default class IABookActions extends LitElement {
|
|
|
602
814
|
this.disableActionGroup = !this.disableActionGroup;
|
|
603
815
|
}
|
|
604
816
|
|
|
605
|
-
|
|
817
|
+
/**
|
|
606
818
|
* handle lending errors occure during different operation like
|
|
607
819
|
* browse book, borrow book, borrowed book token etc...
|
|
608
820
|
*
|
|
@@ -656,16 +868,7 @@ export default class IABookActions extends LitElement {
|
|
|
656
868
|
|
|
657
869
|
/* show error message if something went wrong */
|
|
658
870
|
async showErrorModal(errorMsg, action) {
|
|
659
|
-
|
|
660
|
-
if (!this.modal) {
|
|
661
|
-
this.modal = document.querySelector('modal-manager');
|
|
662
|
-
|
|
663
|
-
// check the DOM if <modal-manager> already there
|
|
664
|
-
if (!this.modal) this.modal = document.createElement('modal-manager');
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
this.modal.id = 'action-bar-modal';
|
|
668
|
-
await document.body.appendChild(this.modal);
|
|
871
|
+
await this.useModalManager();
|
|
669
872
|
|
|
670
873
|
const modalConfig = new ModalConfig({
|
|
671
874
|
title: 'Lending error',
|
|
@@ -676,7 +879,7 @@ export default class IABookActions extends LitElement {
|
|
|
676
879
|
|
|
677
880
|
if (action === 'create_token') {
|
|
678
881
|
const refreshButton = html`<button
|
|
679
|
-
style="
|
|
882
|
+
style="${modalButtonStyle.refresh}"
|
|
680
883
|
@click=${() => window.location.reload(true)}
|
|
681
884
|
>
|
|
682
885
|
refresh
|
|
@@ -693,7 +896,7 @@ export default class IABookActions extends LitElement {
|
|
|
693
896
|
<code>errorLog: ${errorMsg}</code>`;
|
|
694
897
|
}
|
|
695
898
|
|
|
696
|
-
this.modal
|
|
899
|
+
this.modal?.showModal({
|
|
697
900
|
config: modalConfig,
|
|
698
901
|
});
|
|
699
902
|
}
|
|
@@ -188,7 +188,9 @@ describe('Borrow status actions', () => {
|
|
|
188
188
|
},
|
|
189
189
|
];
|
|
190
190
|
|
|
191
|
-
expect(el.primaryTitle).to.equal(
|
|
191
|
+
expect(el.primaryTitle).to.equal(
|
|
192
|
+
'Renews automatically as long as pages are turned.'
|
|
193
|
+
);
|
|
192
194
|
expect(el.primaryActions.length).to.equal(2);
|
|
193
195
|
expect(el.primaryActions[0].text).to.equal('Log In and Borrow');
|
|
194
196
|
expect(el.primaryActions[0].text).to.equal(expectedPrimaryActions[0].text);
|
|
@@ -274,7 +276,7 @@ describe('Browsing expired status', () => {
|
|
|
274
276
|
expect(el.loanRenewResult.renewNow).to.equal(false);
|
|
275
277
|
expect(el.loanRenewResult.secondsLeft).to.equal(0);
|
|
276
278
|
expect(el.loanRenewResult.texts).to.equal(
|
|
277
|
-
'This book has been
|
|
279
|
+
'This book has been returned due to inactivity.'
|
|
278
280
|
);
|
|
279
281
|
});
|
|
280
282
|
|
|
@@ -347,7 +349,7 @@ describe('Auto renew one hour loan', () => {
|
|
|
347
349
|
});
|
|
348
350
|
el.dispatchEvent(myEvent);
|
|
349
351
|
|
|
350
|
-
await aTimeout(
|
|
352
|
+
await aTimeout(1900); // wait for 1.9 second
|
|
351
353
|
await el.updateComplete;
|
|
352
354
|
|
|
353
355
|
expect(el.loanRenewResult.texts).to.equal(
|