@internetarchive/ia-book-actions 0.0.6-8 → 0.0.6-9
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 +43 -10
- package/package.json +3 -2
- package/src/components/collapsible-action-group.js +22 -15
- package/src/core/services/actions-handler/actions-handler-service.js +24 -11
- package/src/core/services/actions-handler/actions-handler.js +41 -7
- package/src/core/services/get-lending-actions.js +4 -1
- package/src/ia-book-actions.js +39 -46
- package/test/components/collapsible-action-group.test.js +27 -0
- package/test/ia-book-actions.test.js +0 -1
- package/src/components/dialog-alert.js +0 -139
package/demo/index.html
CHANGED
|
@@ -72,14 +72,16 @@
|
|
|
72
72
|
margin: 2px;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
body.modal-manager-open {
|
|
76
|
+
overflow: hidden;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
modal-manager {
|
|
80
|
+
display: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
modal-manager[mode='open'] {
|
|
84
|
+
display: block;
|
|
83
85
|
}
|
|
84
86
|
</style>
|
|
85
87
|
</head>
|
|
@@ -95,6 +97,7 @@
|
|
|
95
97
|
defaultLendingStatus,
|
|
96
98
|
canBrowseAndBorrow,
|
|
97
99
|
} from '../src/assets/data/lending-get-status-service.js';
|
|
100
|
+
import { ModalConfig } from '@internetarchive/modal-manager';
|
|
98
101
|
|
|
99
102
|
const userid = '@neeraj-archive';
|
|
100
103
|
const identifier = 'naturalhistoryof00unse_4111';
|
|
@@ -102,13 +105,17 @@
|
|
|
102
105
|
|
|
103
106
|
let iaBookActions = document.querySelector('ia-book-actions');
|
|
104
107
|
|
|
108
|
+
const modalConfig = new ModalConfig();
|
|
109
|
+
modalConfig.headerColor = '#d9534f';
|
|
110
|
+
|
|
105
111
|
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
106
|
-
iaBookActions.userid =
|
|
112
|
+
iaBookActions.userid = userid;
|
|
107
113
|
iaBookActions.identifier = identifier;
|
|
108
114
|
iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
|
|
109
115
|
iaBookActions.lendingStatus = canBrowseAndBorrow;
|
|
110
116
|
iaBookActions.bwbPurchaseUrl = '';
|
|
111
117
|
iaBookActions.barType = '';
|
|
118
|
+
iaBookActions.modalConfig = modalConfig;
|
|
112
119
|
|
|
113
120
|
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
114
121
|
|
|
@@ -122,6 +129,29 @@
|
|
|
122
129
|
});
|
|
123
130
|
});
|
|
124
131
|
|
|
132
|
+
document.querySelectorAll('.errorEnable input[type=checkbox]').forEach((item) => {
|
|
133
|
+
if (window.location.href.indexOf('?error=true') !== -1) {
|
|
134
|
+
item.checked = true;
|
|
135
|
+
}
|
|
136
|
+
item.addEventListener('click', (e) => {
|
|
137
|
+
var searchParams = new URLSearchParams(window.location.search);
|
|
138
|
+
var separate = '';
|
|
139
|
+
if (e.target.checked) {
|
|
140
|
+
separate = '?';
|
|
141
|
+
searchParams.set('error', true);
|
|
142
|
+
} else {
|
|
143
|
+
separate = '';
|
|
144
|
+
searchParams.delete('error');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (history.pushState) {
|
|
148
|
+
var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + separate + searchParams;
|
|
149
|
+
window.history.pushState({path:newurl},'',newurl);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
|
|
125
155
|
document.querySelectorAll('.userState input[type=checkbox]').forEach((item) => {
|
|
126
156
|
item.addEventListener('click', (e) => {
|
|
127
157
|
if (e.target.checked) {
|
|
@@ -156,7 +186,7 @@
|
|
|
156
186
|
if (e.target.value === 'user_has_browsed') {
|
|
157
187
|
lendingStatus1.user_has_browsed = true;
|
|
158
188
|
lendingStatus1.available_to_browse = false;
|
|
159
|
-
lendingStatus1.secondsLeftOnLoan =
|
|
189
|
+
lendingStatus1.secondsLeftOnLoan = 10;
|
|
160
190
|
lendingStatus1.browsingExpired = false;
|
|
161
191
|
} else if(e.target.value === 'browsingExpired') {
|
|
162
192
|
lendingStatus1.user_has_browsed = true;
|
|
@@ -229,6 +259,9 @@
|
|
|
229
259
|
<fieldset>
|
|
230
260
|
<legend>Dev testing for book action bar</legend>
|
|
231
261
|
<table class="initial">
|
|
262
|
+
<tr colspan='5'>
|
|
263
|
+
<td class="errorEnable"><label><input type="checkbox" name="errorEnable" value="errorEnable" />Do you want to see error response?</label></td>
|
|
264
|
+
</tr>
|
|
232
265
|
<tr>
|
|
233
266
|
<td class="userState">
|
|
234
267
|
<label><input type="checkbox" name="user" value="isAdmin" />isAdmin</label>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "0.0.6-
|
|
3
|
+
"version": "0.0.6-9",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@internetarchive/ia-icons": "^1.2.2",
|
|
22
22
|
"@internetarchive/icon-bookmark": "^1.1.3",
|
|
23
|
-
"@internetarchive/icon-info": "^1.2.6",
|
|
24
23
|
"@internetarchive/icon-close": "^1.1.3",
|
|
24
|
+
"@internetarchive/icon-info": "^1.2.6",
|
|
25
|
+
"@internetarchive/modal-manager": "^0.2.1",
|
|
25
26
|
"@internetarchive/shared-resize-observer": "^0.0.1",
|
|
26
27
|
"lit-element": "^2.4.0",
|
|
27
28
|
"lit-html": "^1.3.0"
|
|
@@ -27,7 +27,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
27
27
|
hasAdminAccess: { type: Boolean },
|
|
28
28
|
dropdownArrow: { type: String },
|
|
29
29
|
disabled: { type: Boolean },
|
|
30
|
-
|
|
30
|
+
borrowType: { type: String },
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -46,13 +46,8 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
46
46
|
this.title = '';
|
|
47
47
|
this.loaderIcon = 'https://archive.org/upload/images/tree/loading.gif';
|
|
48
48
|
this.disabled = false;
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
firstUpdated() {
|
|
53
|
-
if (this.bookHasBrowsed) {
|
|
54
|
-
this.emitFetchLoanToken();
|
|
55
|
-
}
|
|
49
|
+
this.borrowType = ''; // (browsed|borrowed)
|
|
50
|
+
this.consecutiveLoanCounts = 1; // consecutive loan count
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
updated(changed) {
|
|
@@ -62,19 +57,31 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
62
57
|
}
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
// this is execute
|
|
66
|
-
if (changed.has('
|
|
67
|
-
this.
|
|
60
|
+
// this is execute to fetch loan token
|
|
61
|
+
if (changed.has('borrowType')) {
|
|
62
|
+
this.emitEnableBookAccess();
|
|
68
63
|
}
|
|
69
64
|
}
|
|
70
65
|
|
|
71
66
|
/* emit custom event to fetch loan token */
|
|
72
|
-
|
|
67
|
+
emitEnableBookAccess() {
|
|
68
|
+
// send consecutiveLoanCounts for browsed books only.
|
|
69
|
+
// for borrowed books, we just send [Counts-1]
|
|
70
|
+
if (this.borrowType === 'browsed') {
|
|
71
|
+
this.consecutiveLoanCounts =
|
|
72
|
+
localStorage.getItem('consecutive-loan-count') ?? 1;
|
|
73
|
+
}
|
|
74
|
+
|
|
73
75
|
this.dispatchEvent(
|
|
74
|
-
new CustomEvent('
|
|
76
|
+
new CustomEvent('enableBookAccess', {
|
|
75
77
|
detail: {
|
|
76
|
-
event: {
|
|
77
|
-
|
|
78
|
+
event: {
|
|
79
|
+
category: `${this.borrowType}BookAccess`, // browsedBookAccess | borrowedBookAccess
|
|
80
|
+
action: `${
|
|
81
|
+
this.borrowType === 'browsed' ? 'BrowseCounts-' : 'Counts-'
|
|
82
|
+
}${this.consecutiveLoanCounts}`, // (BrowseCounts-1|Counts-X)
|
|
83
|
+
},
|
|
84
|
+
borrowType: this.borrowType,
|
|
78
85
|
},
|
|
79
86
|
})
|
|
80
87
|
);
|
|
@@ -29,19 +29,32 @@ export default function ActionsHandlerService(options) {
|
|
|
29
29
|
body: formData,
|
|
30
30
|
})
|
|
31
31
|
.then(response => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
let shouldReturnError =
|
|
33
|
+
window.location.href.indexOf('?error=true') !== -1;
|
|
34
|
+
const tokenError = 'loan token not found. please try again later.';
|
|
35
|
+
const borrowError =
|
|
36
|
+
'This book is not available to borrow at this time. Please try again later.';
|
|
37
|
+
|
|
38
|
+
// return error reponse if query param has ?error=true param...
|
|
39
|
+
if (option.action == 'create_token' && shouldReturnError) {
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
error: tokenError,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
41
45
|
|
|
46
|
+
if (shouldReturnError) {
|
|
47
|
+
return {
|
|
48
|
+
status: true,
|
|
49
|
+
error: borrowError,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// return success response for /demo/ server...
|
|
54
|
+
if (baseHost == '/demo/1' || baseHost == '/demo/') {
|
|
42
55
|
return {
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
success: true,
|
|
57
|
+
message: 'operation executed successfully!',
|
|
45
58
|
};
|
|
46
59
|
}
|
|
47
60
|
|
|
@@ -15,24 +15,37 @@ export default class ActionsHandler extends LitElement {
|
|
|
15
15
|
super();
|
|
16
16
|
this.identifier = identifier;
|
|
17
17
|
this.ajaxTimeout = 6000;
|
|
18
|
-
this.loanTokenPollingDelay =
|
|
18
|
+
this.loanTokenPollingDelay =
|
|
19
|
+
window.location.pathname === '/demo/' ? 2000 : 120000; // 120000 ms = 2 min
|
|
19
20
|
this.loanTokenInterval = null;
|
|
20
21
|
this.bindEvents();
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
disconnectedCallback() {
|
|
25
|
+
this.loanTokenInterval = undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
sendEvent(eventCategory, eventAction) {
|
|
24
29
|
// eslint-disable-next-line no-console
|
|
25
30
|
console?.log('Book action: ', { eventCategory, eventAction });
|
|
26
|
-
window?.archive_analytics?.
|
|
31
|
+
window?.archive_analytics?.send_event_no_sampling(
|
|
27
32
|
eventCategory,
|
|
28
33
|
eventAction,
|
|
29
|
-
|
|
34
|
+
`identifier=${this.identifier}`
|
|
30
35
|
);
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
bindEvents() {
|
|
34
39
|
this.addEventListener('browseBook', ({ detail }) => {
|
|
35
40
|
this.handleBrowseIt();
|
|
41
|
+
this.setConsecutiveLoanCounts();
|
|
42
|
+
const { category, action } = detail.event;
|
|
43
|
+
this.sendEvent(category, action);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.addEventListener('browseBookAgain', ({ detail }) => {
|
|
47
|
+
this.handleBrowseIt();
|
|
48
|
+
this.setConsecutiveLoanCounts('browseAgain');
|
|
36
49
|
const { category, action } = detail.event;
|
|
37
50
|
this.sendEvent(category, action);
|
|
38
51
|
});
|
|
@@ -87,16 +100,19 @@ export default class ActionsHandler extends LitElement {
|
|
|
87
100
|
this.sendEvent(category, action);
|
|
88
101
|
});
|
|
89
102
|
|
|
90
|
-
this.addEventListener('
|
|
91
|
-
const
|
|
103
|
+
this.addEventListener('enableBookAccess', ({ detail }) => {
|
|
104
|
+
const borrowType = detail?.borrowType;
|
|
92
105
|
|
|
93
|
-
// fetch loan token and set an interval
|
|
94
|
-
if (
|
|
106
|
+
// fetch loan token for browsed/borrowed book and set an interval
|
|
107
|
+
if (borrowType) {
|
|
95
108
|
console.log('token poll started...');
|
|
96
109
|
|
|
97
110
|
this.loanTokenInterval = setInterval(() => {
|
|
98
111
|
this.handleLoanTokenPoller();
|
|
99
112
|
}, this.loanTokenPollingDelay);
|
|
113
|
+
|
|
114
|
+
const { category, action } = detail?.event;
|
|
115
|
+
this.sendEvent(category, action);
|
|
100
116
|
} else {
|
|
101
117
|
// if book is not browsed, just clear token polling interval
|
|
102
118
|
clearInterval(this.loanTokenInterval);
|
|
@@ -192,6 +208,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
192
208
|
action: context,
|
|
193
209
|
error: data => {
|
|
194
210
|
this.ActionError(context, data);
|
|
211
|
+
clearInterval(this.loanTokenInterval); // stop token fetch api
|
|
195
212
|
},
|
|
196
213
|
});
|
|
197
214
|
}
|
|
@@ -236,6 +253,23 @@ export default class ActionsHandler extends LitElement {
|
|
|
236
253
|
}, this.ajaxTimeout);
|
|
237
254
|
}
|
|
238
255
|
|
|
256
|
+
// save consecutive loan count for borrow
|
|
257
|
+
setConsecutiveLoanCounts(action = '') {
|
|
258
|
+
const { localStorage } = window;
|
|
259
|
+
if (localStorage) {
|
|
260
|
+
let newCount = 1;
|
|
261
|
+
const storageKey = `consecutive-loan-count`;
|
|
262
|
+
const existingCount = Number(localStorage.getItem(storageKey));
|
|
263
|
+
|
|
264
|
+
// want to increase browse-count by 1 if,
|
|
265
|
+
// you consecutive reading a book.
|
|
266
|
+
if (action === 'browseAgain') {
|
|
267
|
+
newCount = existingCount ? existingCount + 1 : 1;
|
|
268
|
+
}
|
|
269
|
+
localStorage.setItem(storageKey, newCount);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
239
273
|
deleteLoanCookies() {
|
|
240
274
|
const date = new Date();
|
|
241
275
|
date.setTime(date.getTime() - 24 * 60 * 60 * 1000); // one day ago
|
|
@@ -75,7 +75,9 @@ export default class GetLendingActions {
|
|
|
75
75
|
const disableBorrow = lendingStatus.loanCount >= lendingStatus.maxLoans;
|
|
76
76
|
|
|
77
77
|
let primaryTitleText = '';
|
|
78
|
-
|
|
78
|
+
let isBrowsed =
|
|
79
|
+
lendingStatus.user_has_browsed && !lendingStatus.browsingExpired;
|
|
80
|
+
if (isBrowsed) {
|
|
79
81
|
primaryTitleText = this.getBrowseCountdownTitle();
|
|
80
82
|
} else {
|
|
81
83
|
primaryTitleText = `Your loan of this book has ${lendingStatus.daysLeftOnLoan} days left.`;
|
|
@@ -94,6 +96,7 @@ export default class GetLendingActions {
|
|
|
94
96
|
this.actionsConfig.adminAccessConfig(),
|
|
95
97
|
this.actionsConfig.purchaseConfig(),
|
|
96
98
|
],
|
|
99
|
+
borrowType: isBrowsed ? 'browsed' : 'borrowed',
|
|
97
100
|
};
|
|
98
101
|
}
|
|
99
102
|
|
package/src/ia-book-actions.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { html, css, LitElement } from 'lit-element';
|
|
3
3
|
|
|
4
4
|
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
|
5
|
+
import { ModalConfig } from '@internetarchive/modal-manager';
|
|
5
6
|
|
|
6
7
|
import './components/collapsible-action-group.js';
|
|
7
8
|
import './components/book-title-bar.js';
|
|
8
9
|
import './components/text-group.js';
|
|
9
10
|
import './components/info-icon.js';
|
|
10
|
-
import './components/dialog-alert.js';
|
|
11
11
|
|
|
12
12
|
import GetLendingActions from './core/services/get-lending-actions.js';
|
|
13
13
|
import { mobileContainerWidth } from './core/config/constants.js';
|
|
@@ -23,9 +23,8 @@ export default class IABookActions extends LitElement {
|
|
|
23
23
|
bwbPurchaseUrl: { type: String },
|
|
24
24
|
barType: { type: String },
|
|
25
25
|
sharedObserver: { attribute: false },
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
bookHasBrowsed: { type: Boolean },
|
|
26
|
+
disableActionGroup: { type: Boolean },
|
|
27
|
+
modalConfig: { type: Object },
|
|
29
28
|
};
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -45,8 +44,7 @@ export default class IABookActions extends LitElement {
|
|
|
45
44
|
this.secondaryActions = [];
|
|
46
45
|
this.lendingOptions = {};
|
|
47
46
|
this.disableActionGroup = false;
|
|
48
|
-
this.
|
|
49
|
-
this.bookHasBrowsed = false;
|
|
47
|
+
this.modalConfig = {};
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
disconnectedCallback() {
|
|
@@ -58,6 +56,11 @@ export default class IABookActions extends LitElement {
|
|
|
58
56
|
this.sharedObserver = new SharedResizeObserver();
|
|
59
57
|
this.setupResizeObserver();
|
|
60
58
|
}
|
|
59
|
+
|
|
60
|
+
if (!Object.keys(this.modalConfig).length) {
|
|
61
|
+
this.modalConfig = new ModalConfig();
|
|
62
|
+
this.modalConfig.headerColor = '#d9534f';
|
|
63
|
+
}
|
|
61
64
|
this.setupLendingToolbarActions();
|
|
62
65
|
}
|
|
63
66
|
|
|
@@ -146,12 +149,10 @@ export default class IABookActions extends LitElement {
|
|
|
146
149
|
return action != null;
|
|
147
150
|
});
|
|
148
151
|
|
|
149
|
-
this.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
// start timer for 1-hour borrowed book.
|
|
154
|
-
// when 1 hour is completed, we shows browse-again button
|
|
152
|
+
this.borrowType = actions.borrowType;
|
|
153
|
+
if (this.borrowType === 'browsed') {
|
|
154
|
+
// start timer for browsed.
|
|
155
|
+
// when browse is completed, we shows browse-again button
|
|
155
156
|
this.startBrowseTimer();
|
|
156
157
|
}
|
|
157
158
|
}
|
|
@@ -161,21 +162,9 @@ export default class IABookActions extends LitElement {
|
|
|
161
162
|
<section class="lending-wrapper">
|
|
162
163
|
${this.barType === 'title' ? this.bookTitleBar : this.bookActionBar}
|
|
163
164
|
</section>
|
|
164
|
-
|
|
165
|
-
<show-dialog
|
|
166
|
-
.title=${this.dialogTitle}
|
|
167
|
-
.body=${this.dialogBody}
|
|
168
|
-
.actions=${this.dialogActions}
|
|
169
|
-
?opened="${this.dialogVisible}"
|
|
170
|
-
@dialogAlertClose="${() => this.closeDialogAlert()}"
|
|
171
|
-
></show-dialog>
|
|
172
165
|
`;
|
|
173
166
|
}
|
|
174
167
|
|
|
175
|
-
closeDialogAlert() {
|
|
176
|
-
this.dialogVisible = false;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
168
|
get bookTitleBar() {
|
|
180
169
|
return html`<book-title-bar
|
|
181
170
|
.identifier=${this.identifier}
|
|
@@ -192,9 +181,9 @@ export default class IABookActions extends LitElement {
|
|
|
192
181
|
.primaryActions=${this.primaryActions}
|
|
193
182
|
.secondaryActions=${this.secondaryActions}
|
|
194
183
|
.width=${this.width}
|
|
195
|
-
.
|
|
196
|
-
|
|
197
|
-
|
|
184
|
+
.borrowType=${this.borrowType}
|
|
185
|
+
?hasAdminAccess=${this.hasAdminAccess}
|
|
186
|
+
?disabled=${this.disableActionGroup}
|
|
198
187
|
@lendingActionError=${this.handleLendingActionError}
|
|
199
188
|
>
|
|
200
189
|
</collapsible-action-group>
|
|
@@ -202,6 +191,10 @@ export default class IABookActions extends LitElement {
|
|
|
202
191
|
`;
|
|
203
192
|
}
|
|
204
193
|
|
|
194
|
+
/*
|
|
195
|
+
* handle lending errors occure on different operation like
|
|
196
|
+
* browse book, borrow book, borrowed book token etc...
|
|
197
|
+
*/
|
|
205
198
|
handleLendingActionError(e) {
|
|
206
199
|
// toggle activity loader
|
|
207
200
|
this.disableActionGroup = !this.disableActionGroup;
|
|
@@ -209,10 +202,7 @@ export default class IABookActions extends LitElement {
|
|
|
209
202
|
const context = e?.detail?.context;
|
|
210
203
|
const errorMsg = e?.detail?.data?.error;
|
|
211
204
|
|
|
212
|
-
|
|
213
|
-
if (!errorMsg) return;
|
|
214
|
-
|
|
215
|
-
this.initializeDialogAlert(context, errorMsg);
|
|
205
|
+
if (errorMsg) this.showErrorModal(context, errorMsg);
|
|
216
206
|
|
|
217
207
|
// update action bar state if book is not available to browse or borrow.
|
|
218
208
|
if (errorMsg && errorMsg.match(/not available to borrow/gm)) {
|
|
@@ -232,22 +222,25 @@ export default class IABookActions extends LitElement {
|
|
|
232
222
|
}
|
|
233
223
|
}
|
|
234
224
|
|
|
235
|
-
/*
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this.
|
|
239
|
-
this.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
className: 'ia-button primary',
|
|
246
|
-
text: 'Back to Item Details',
|
|
247
|
-
href: `/details/${this.lendingStatus.bookUrl}`,
|
|
248
|
-
},
|
|
249
|
-
];
|
|
225
|
+
/* show error message if something went wrong */
|
|
226
|
+
async showErrorModal(context, errorMsg) {
|
|
227
|
+
// add modal-manager in DOM to show alert message
|
|
228
|
+
this.modal = document.createElement('modal-manager');
|
|
229
|
+
await document.body.appendChild(this.modal);
|
|
230
|
+
|
|
231
|
+
// fallback if <modal-manager> is not found!
|
|
232
|
+
if (!this.modal) {
|
|
233
|
+
alert(errorMsg);
|
|
234
|
+
return;
|
|
250
235
|
}
|
|
236
|
+
|
|
237
|
+
this.disableActionGroup = false;
|
|
238
|
+
this.modalConfig.title = 'Sorry!';
|
|
239
|
+
this.modalConfig.message = errorMsg;
|
|
240
|
+
|
|
241
|
+
this.modal.showModal({
|
|
242
|
+
config: this.modalConfig,
|
|
243
|
+
});
|
|
251
244
|
}
|
|
252
245
|
|
|
253
246
|
get iconClass() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { html, fixture, expect } from '@open-wc/testing';
|
|
2
2
|
import '../../src/components/collapsible-action-group.js';
|
|
3
|
+
import Sinon from 'sinon';
|
|
3
4
|
|
|
4
5
|
const container = ({
|
|
5
6
|
primaryActions = [
|
|
@@ -23,10 +24,12 @@ const container = ({
|
|
|
23
24
|
text: 'Purchase',
|
|
24
25
|
},
|
|
25
26
|
],
|
|
27
|
+
borrowType = '',
|
|
26
28
|
} = {}) =>
|
|
27
29
|
html`<collapsible-action-group
|
|
28
30
|
.primaryActions=${primaryActions}
|
|
29
31
|
.secondaryActions=${secondaryActions}
|
|
32
|
+
.borrowType=${borrowType}
|
|
30
33
|
></collapsible-action-group>`;
|
|
31
34
|
|
|
32
35
|
describe('<collapsible-action-group>', () => {
|
|
@@ -82,3 +85,27 @@ describe('<collapsible-action-group>', () => {
|
|
|
82
85
|
expect(eAnalytics.action).to.equal('Browse');
|
|
83
86
|
});
|
|
84
87
|
});
|
|
88
|
+
|
|
89
|
+
describe('fetch loan token and localStorage for browsed/borrowsed book', () => {
|
|
90
|
+
beforeEach(() => {
|
|
91
|
+
const localStorageMock = {
|
|
92
|
+
getItem: Sinon.spy(),
|
|
93
|
+
setItem: Sinon.spy(),
|
|
94
|
+
};
|
|
95
|
+
Object.defineProperty(window, 'localStorage', {
|
|
96
|
+
value: localStorageMock,
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('test localStorage function when borrowType is browsed', async () => {
|
|
101
|
+
await fixture(container({ borrowType: 'browsed' }));
|
|
102
|
+
expect(localStorage.getItem).to.be.calledOnce;
|
|
103
|
+
expect(localStorage.getItem).to.be.calledWith('consecutive-loan-count');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('test localStorage function when borrowType is borrowed', async () => {
|
|
107
|
+
await fixture(container({ borrowType: 'borrowed' }));
|
|
108
|
+
expect(localStorage.getItem).to.not.be.calledOnce;
|
|
109
|
+
expect(localStorage.getItem).to.not.be.calledWith('consecutive-loan-count');
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -130,7 +130,6 @@ describe('Borrow status actions', () => {
|
|
|
130
130
|
el.dispatchEvent(errorEvent);
|
|
131
131
|
await el.updateComplete;
|
|
132
132
|
|
|
133
|
-
console.log(el.lendingStatus);
|
|
134
133
|
// removed available_to_browse from lending bar
|
|
135
134
|
expect(el.lendingStatus.available_to_browse).to.be.false;
|
|
136
135
|
expect(el.primaryActions[0].text).to.equal('Borrow for 14 days');
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
import { LitElement, html, css } from 'lit-element';
|
|
3
|
-
import { classMap } from 'lit-html/directives/class-map';
|
|
4
|
-
|
|
5
|
-
import '@internetarchive/icon-close/icon-close.js';
|
|
6
|
-
import buttonBaseStyle from '../assets/styles/ia-button.js';
|
|
7
|
-
|
|
8
|
-
export class ShowDialog extends LitElement {
|
|
9
|
-
static get properties() {
|
|
10
|
-
return {
|
|
11
|
-
title: { type: String },
|
|
12
|
-
body: { type: String },
|
|
13
|
-
actions: { type: Array },
|
|
14
|
-
opened: { type: Boolean },
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
constructor() {
|
|
19
|
-
super();
|
|
20
|
-
this.title = 'Error';
|
|
21
|
-
this.body =
|
|
22
|
-
'Unexpected error: loan does not exist. Please try deleting your archive.org cookie.';
|
|
23
|
-
this.actions = [];
|
|
24
|
-
this.opened = false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
updated(changed) {
|
|
28
|
-
if (changed.get('opened') === false) {
|
|
29
|
-
this.addOverlay();
|
|
30
|
-
} else {
|
|
31
|
-
this.removeOverlay();
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
render() {
|
|
36
|
-
return html`
|
|
37
|
-
<div
|
|
38
|
-
class="${classMap({
|
|
39
|
-
dialog: true,
|
|
40
|
-
opened: this.opened,
|
|
41
|
-
closed: !this.opened,
|
|
42
|
-
})}"
|
|
43
|
-
>
|
|
44
|
-
<div class="dialog-head">
|
|
45
|
-
${this.title}
|
|
46
|
-
<ia-icon-close
|
|
47
|
-
@click="${() =>
|
|
48
|
-
this.dispatchEvent(new CustomEvent('dialogAlertClose'))}"
|
|
49
|
-
></ia-icon-close>
|
|
50
|
-
</div>
|
|
51
|
-
<div class="dialog-body">${this.body}</div>
|
|
52
|
-
<div class="dialog-foot">${this.renderActionButton}</div>
|
|
53
|
-
</div>
|
|
54
|
-
`;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/* exceptional case to use dom element */
|
|
58
|
-
addOverlay() {
|
|
59
|
-
if (this.opened && !document.getElementById('ui-overlay')) {
|
|
60
|
-
const overlayElement = document.createElement('div');
|
|
61
|
-
overlayElement.id = 'ui-overlay';
|
|
62
|
-
document.getElementsByTagName('body')[0].appendChild(overlayElement);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/* exceptional case to use dom element */
|
|
67
|
-
removeOverlay() {
|
|
68
|
-
const overlayElement = document.getElementById('ui-overlay');
|
|
69
|
-
if (overlayElement) overlayElement.remove();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get renderActionButton() {
|
|
73
|
-
if (!this.actions) return;
|
|
74
|
-
|
|
75
|
-
return this.actions.map(
|
|
76
|
-
action =>
|
|
77
|
-
html`<a class=${action.className} href=${action.href}>
|
|
78
|
-
${action.text}
|
|
79
|
-
</button>`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
static get styles() {
|
|
84
|
-
const dialogStyle = css`
|
|
85
|
-
:host {
|
|
86
|
-
color: #343434;
|
|
87
|
-
font-size: 1.6rem;
|
|
88
|
-
}
|
|
89
|
-
.dialog {
|
|
90
|
-
position: absolute;
|
|
91
|
-
background: #fff;
|
|
92
|
-
border-radius: 1.2rem;
|
|
93
|
-
z-index: 3000;
|
|
94
|
-
flex-direction: column;
|
|
95
|
-
min-width: 300px;
|
|
96
|
-
max-width: 400px;
|
|
97
|
-
left: 50%;
|
|
98
|
-
transform: translateX(-50%);
|
|
99
|
-
|
|
100
|
-
border: 2px solid #ccc;
|
|
101
|
-
border-radius: 12px;
|
|
102
|
-
box-shadow: 0px 0px 27px 6px rgb(66 66 66 / 80%);
|
|
103
|
-
}
|
|
104
|
-
.dialog-head,
|
|
105
|
-
.dialog-body,
|
|
106
|
-
.dialog-foot {
|
|
107
|
-
padding: 1rem;
|
|
108
|
-
user-select: none;
|
|
109
|
-
text-align: left;
|
|
110
|
-
}
|
|
111
|
-
.dialog-body {
|
|
112
|
-
border: 1px solid #d8d8d8;
|
|
113
|
-
}
|
|
114
|
-
ia-icon-close {
|
|
115
|
-
position: absolute;
|
|
116
|
-
right: 0.5rem;
|
|
117
|
-
top: 0.5rem;
|
|
118
|
-
width: 2.5rem;
|
|
119
|
-
height: 2.5rem;
|
|
120
|
-
vertical-align: middle;
|
|
121
|
-
--iconFillColor: #333;
|
|
122
|
-
cursor: pointer;
|
|
123
|
-
}
|
|
124
|
-
.opened {
|
|
125
|
-
display: flex;
|
|
126
|
-
}
|
|
127
|
-
.closed {
|
|
128
|
-
display: none;
|
|
129
|
-
}
|
|
130
|
-
a {
|
|
131
|
-
text-decoration: none;
|
|
132
|
-
}
|
|
133
|
-
`;
|
|
134
|
-
|
|
135
|
-
return [buttonBaseStyle, dialogStyle];
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
customElements.define('show-dialog', ShowDialog);
|