@internetarchive/ia-book-actions 0.0.6-5 → 0.0.6-8-01
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 +11 -1
- package/package.json +2 -1
- package/src/assets/styles/collapsible-action-group.js +3 -0
- package/src/components/collapsible-action-group.js +28 -0
- package/src/components/dialog-alert.js +144 -0
- package/src/core/services/actions-handler/actions-handler-service.js +14 -7
- package/src/core/services/actions-handler/actions-handler.js +49 -26
- package/src/ia-book-actions.js +71 -20
- package/test/components/dialog-alert.test.js +62 -0
- package/test/ia-book-actions.test.js +58 -0
package/demo/index.html
CHANGED
|
@@ -71,6 +71,16 @@
|
|
|
71
71
|
float: left;
|
|
72
72
|
margin: 2px;
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
#ui-overlay {
|
|
76
|
+
position: fixed;
|
|
77
|
+
top: 0;
|
|
78
|
+
left: 0;
|
|
79
|
+
width: 100%;
|
|
80
|
+
height: 100%;
|
|
81
|
+
background: black;
|
|
82
|
+
opacity: 0.3;
|
|
83
|
+
}
|
|
74
84
|
</style>
|
|
75
85
|
</head>
|
|
76
86
|
|
|
@@ -146,7 +156,7 @@
|
|
|
146
156
|
if (e.target.value === 'user_has_browsed') {
|
|
147
157
|
lendingStatus1.user_has_browsed = true;
|
|
148
158
|
lendingStatus1.available_to_browse = false;
|
|
149
|
-
lendingStatus1.secondsLeftOnLoan =
|
|
159
|
+
lendingStatus1.secondsLeftOnLoan = 30;
|
|
150
160
|
lendingStatus1.browsingExpired = false;
|
|
151
161
|
} else if(e.target.value === 'browsingExpired') {
|
|
152
162
|
lendingStatus1.user_has_browsed = true;
|
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-8-01",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"@internetarchive/ia-icons": "^1.2.2",
|
|
22
22
|
"@internetarchive/icon-bookmark": "^1.1.3",
|
|
23
23
|
"@internetarchive/icon-info": "^1.2.6",
|
|
24
|
+
"@internetarchive/icon-close": "^1.1.3",
|
|
24
25
|
"@internetarchive/shared-resize-observer": "^0.0.1",
|
|
25
26
|
"lit-element": "^2.4.0",
|
|
26
27
|
"lit-html": "^1.3.0"
|
|
@@ -27,6 +27,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
27
27
|
hasAdminAccess: { type: Boolean },
|
|
28
28
|
dropdownArrow: { type: String },
|
|
29
29
|
disabled: { type: Boolean },
|
|
30
|
+
bookHasBrowsed: { type: Boolean },
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -45,6 +46,13 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
45
46
|
this.title = '';
|
|
46
47
|
this.loaderIcon = 'https://archive.org/upload/images/tree/loading.gif';
|
|
47
48
|
this.disabled = false;
|
|
49
|
+
this.bookHasBrowsed = false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
firstUpdated() {
|
|
53
|
+
if (this.bookHasBrowsed) {
|
|
54
|
+
this.emitFetchLoanToken();
|
|
55
|
+
}
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
updated(changed) {
|
|
@@ -53,6 +61,26 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
53
61
|
this.resetActions();
|
|
54
62
|
}
|
|
55
63
|
}
|
|
64
|
+
|
|
65
|
+
// this is execute on demo page only
|
|
66
|
+
if (
|
|
67
|
+
changed.has('bookHasBrowsed') &&
|
|
68
|
+
window.location.pathname === '/demo/'
|
|
69
|
+
) {
|
|
70
|
+
this.emitFetchLoanToken();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* emit custom event to fetch loan token */
|
|
75
|
+
emitFetchLoanToken() {
|
|
76
|
+
this.dispatchEvent(
|
|
77
|
+
new CustomEvent('fetchLoanToken', {
|
|
78
|
+
detail: {
|
|
79
|
+
event: { category: 'action' },
|
|
80
|
+
bookHasBrowsed: this.bookHasBrowsed,
|
|
81
|
+
},
|
|
82
|
+
})
|
|
83
|
+
);
|
|
56
84
|
}
|
|
57
85
|
|
|
58
86
|
/**
|
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
allowClose: { type: Boolean },
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
this.title = 'Error';
|
|
22
|
+
this.body =
|
|
23
|
+
'Unexpected error: loan does not exist. Please try deleting your archive.org cookie.';
|
|
24
|
+
this.actions = [];
|
|
25
|
+
this.opened = false;
|
|
26
|
+
this.allowClose = false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
updated(changed) {
|
|
30
|
+
if (changed.get('opened') === false) {
|
|
31
|
+
this.addOverlay();
|
|
32
|
+
} else {
|
|
33
|
+
this.removeOverlay();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
render() {
|
|
38
|
+
return html`
|
|
39
|
+
<div
|
|
40
|
+
class="${classMap({
|
|
41
|
+
dialog: true,
|
|
42
|
+
opened: this.opened,
|
|
43
|
+
closed: !this.opened,
|
|
44
|
+
})}"
|
|
45
|
+
>
|
|
46
|
+
<div class="dialog-head">${this.title} ${this.closeButton}</div>
|
|
47
|
+
<div class="dialog-body">${this.body}</div>
|
|
48
|
+
<div class="dialog-foot">${this.renderActionButton}</div>
|
|
49
|
+
</div>
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get closeButton() {
|
|
54
|
+
return this.allowClose
|
|
55
|
+
? html`<ia-icon-close
|
|
56
|
+
@click="${() =>
|
|
57
|
+
this.dispatchEvent(new CustomEvent('dialogAlertClose'))}"
|
|
58
|
+
></ia-icon-close>`
|
|
59
|
+
: html``;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* exceptional case to use dom element */
|
|
63
|
+
addOverlay() {
|
|
64
|
+
if (this.opened && !document.getElementById('ui-overlay')) {
|
|
65
|
+
const overlayElement = document.createElement('div');
|
|
66
|
+
overlayElement.id = 'ui-overlay';
|
|
67
|
+
document.getElementsByTagName('body')[0].appendChild(overlayElement);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* exceptional case to use dom element */
|
|
72
|
+
removeOverlay() {
|
|
73
|
+
const overlayElement = document.getElementById('ui-overlay');
|
|
74
|
+
if (overlayElement) overlayElement.remove();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get renderActionButton() {
|
|
78
|
+
if (!this.actions) return;
|
|
79
|
+
|
|
80
|
+
return this.actions.map(
|
|
81
|
+
action =>
|
|
82
|
+
html`<a class=${action.className} href=${action.href}>
|
|
83
|
+
${action.text}
|
|
84
|
+
</button>`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static get styles() {
|
|
89
|
+
const dialogStyle = css`
|
|
90
|
+
:host {
|
|
91
|
+
color: #343434;
|
|
92
|
+
font-size: 1.6rem;
|
|
93
|
+
}
|
|
94
|
+
.dialog {
|
|
95
|
+
position: absolute;
|
|
96
|
+
background: #fff;
|
|
97
|
+
border-radius: 1.2rem;
|
|
98
|
+
z-index: 3000;
|
|
99
|
+
flex-direction: column;
|
|
100
|
+
min-width: 300px;
|
|
101
|
+
max-width: 400px;
|
|
102
|
+
left: 50%;
|
|
103
|
+
transform: translateX(-50%);
|
|
104
|
+
|
|
105
|
+
border: 2px solid #ccc;
|
|
106
|
+
border-radius: 12px;
|
|
107
|
+
box-shadow: 0px 0px 27px 6px rgb(66 66 66 / 80%);
|
|
108
|
+
}
|
|
109
|
+
.dialog-head,
|
|
110
|
+
.dialog-body,
|
|
111
|
+
.dialog-foot {
|
|
112
|
+
padding: 1rem;
|
|
113
|
+
user-select: none;
|
|
114
|
+
text-align: left;
|
|
115
|
+
}
|
|
116
|
+
.dialog-body {
|
|
117
|
+
border: 1px solid #d8d8d8;
|
|
118
|
+
}
|
|
119
|
+
ia-icon-close {
|
|
120
|
+
position: absolute;
|
|
121
|
+
right: 0.5rem;
|
|
122
|
+
top: 0.5rem;
|
|
123
|
+
width: 2.5rem;
|
|
124
|
+
height: 2.5rem;
|
|
125
|
+
vertical-align: middle;
|
|
126
|
+
--iconFillColor: #333;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
}
|
|
129
|
+
.opened {
|
|
130
|
+
display: flex;
|
|
131
|
+
}
|
|
132
|
+
.closed {
|
|
133
|
+
display: none;
|
|
134
|
+
}
|
|
135
|
+
a {
|
|
136
|
+
text-decoration: none;
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
|
|
140
|
+
return [buttonBaseStyle, dialogStyle];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
customElements.define('show-dialog', ShowDialog);
|
|
@@ -8,17 +8,14 @@ export default function ActionsHandlerService(options) {
|
|
|
8
8
|
const option = {
|
|
9
9
|
action: null,
|
|
10
10
|
identifier: '',
|
|
11
|
-
data: {},
|
|
12
11
|
success() {},
|
|
13
12
|
error() {},
|
|
14
|
-
loader: true,
|
|
15
|
-
type: 'POST',
|
|
16
13
|
...options,
|
|
17
14
|
};
|
|
18
15
|
|
|
19
16
|
let baseHost = '';
|
|
20
17
|
if (window.location.pathname === '/demo/') {
|
|
21
|
-
baseHost = `/demo
|
|
18
|
+
baseHost = `/demo/`;
|
|
22
19
|
} else {
|
|
23
20
|
baseHost = `/services/loans/loan`;
|
|
24
21
|
}
|
|
@@ -34,9 +31,20 @@ export default function ActionsHandlerService(options) {
|
|
|
34
31
|
.then(response => {
|
|
35
32
|
// test changes, (won't affect you)
|
|
36
33
|
if (baseHost == '/demo/1' || baseHost == '/demo/') {
|
|
34
|
+
if (option.action == 'create_token') {
|
|
35
|
+
return {
|
|
36
|
+
success: false,
|
|
37
|
+
error: 'loan token not found. please try again later.',
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
token: '1640945898-f77a0cb615190798f1faf2dafe277b2e',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
37
45
|
return {
|
|
38
|
-
error:
|
|
39
|
-
|
|
46
|
+
error:
|
|
47
|
+
'This book is not available to borrow at this time. Please try again later.',
|
|
40
48
|
};
|
|
41
49
|
}
|
|
42
50
|
|
|
@@ -46,7 +54,6 @@ export default function ActionsHandlerService(options) {
|
|
|
46
54
|
})
|
|
47
55
|
.then(data => {
|
|
48
56
|
// `data` is the parsed version of the JSON returned from the above endpoint.
|
|
49
|
-
console.log('actual reponse for endpoint', data);
|
|
50
57
|
if (!data.error) {
|
|
51
58
|
option?.success(data);
|
|
52
59
|
} else {
|
|
@@ -15,6 +15,9 @@ export default class ActionsHandler extends LitElement {
|
|
|
15
15
|
super();
|
|
16
16
|
this.identifier = identifier;
|
|
17
17
|
this.ajaxTimeout = 6000;
|
|
18
|
+
this.loanTokenPollingDelay =
|
|
19
|
+
window.location.pathname === '/demo/' ? 2000 : 20000; // 20000 ms = 20 sec
|
|
20
|
+
this.loanTokenInterval = null;
|
|
18
21
|
this.bindEvents();
|
|
19
22
|
}
|
|
20
23
|
|
|
@@ -84,11 +87,27 @@ export default class ActionsHandler extends LitElement {
|
|
|
84
87
|
const { category, action } = detail.event;
|
|
85
88
|
this.sendEvent(category, action);
|
|
86
89
|
});
|
|
90
|
+
|
|
91
|
+
this.addEventListener('fetchLoanToken', ({ detail }) => {
|
|
92
|
+
const bookHasBrowsed = detail?.bookHasBrowsed;
|
|
93
|
+
|
|
94
|
+
// fetch loan token and set an interval
|
|
95
|
+
if (bookHasBrowsed) {
|
|
96
|
+
console.log('token poll started...');
|
|
97
|
+
|
|
98
|
+
this.loanTokenInterval = setInterval(() => {
|
|
99
|
+
this.handleLoanTokenPoller();
|
|
100
|
+
}, this.loanTokenPollingDelay);
|
|
101
|
+
} else {
|
|
102
|
+
// if book is not browsed, just clear token polling interval
|
|
103
|
+
clearInterval(this.loanTokenInterval);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
87
106
|
}
|
|
88
107
|
|
|
89
108
|
handleBrowseIt() {
|
|
90
109
|
const context = 'browse_book';
|
|
91
|
-
this.
|
|
110
|
+
this.ActionError(context);
|
|
92
111
|
|
|
93
112
|
ActionsHandlerService({
|
|
94
113
|
action: context,
|
|
@@ -97,15 +116,14 @@ export default class ActionsHandler extends LitElement {
|
|
|
97
116
|
this.handleReadItNow();
|
|
98
117
|
},
|
|
99
118
|
error: data => {
|
|
100
|
-
|
|
101
|
-
this.toggleActionBarState(context, data);
|
|
119
|
+
this.ActionError(context, data);
|
|
102
120
|
},
|
|
103
121
|
});
|
|
104
122
|
}
|
|
105
123
|
|
|
106
124
|
handleReturnIt() {
|
|
107
125
|
const context = 'return_loan';
|
|
108
|
-
this.
|
|
126
|
+
this.ActionError(context);
|
|
109
127
|
|
|
110
128
|
ActionsHandlerService({
|
|
111
129
|
action: context,
|
|
@@ -115,15 +133,14 @@ export default class ActionsHandler extends LitElement {
|
|
|
115
133
|
URLHelper.goToUrl(`/details/${this.identifier}`, true);
|
|
116
134
|
},
|
|
117
135
|
error: data => {
|
|
118
|
-
|
|
119
|
-
this.toggleActionBarState(context);
|
|
136
|
+
this.ActionError(context, data);
|
|
120
137
|
},
|
|
121
138
|
});
|
|
122
139
|
}
|
|
123
140
|
|
|
124
141
|
handleBorrowIt() {
|
|
125
142
|
const context = 'borrow_book';
|
|
126
|
-
this.
|
|
143
|
+
this.ActionError(context);
|
|
127
144
|
|
|
128
145
|
ActionsHandlerService({
|
|
129
146
|
action: context,
|
|
@@ -132,15 +149,14 @@ export default class ActionsHandler extends LitElement {
|
|
|
132
149
|
this.handleReadItNow();
|
|
133
150
|
},
|
|
134
151
|
error: data => {
|
|
135
|
-
|
|
136
|
-
this.toggleActionBarState(context, data);
|
|
152
|
+
this.ActionError(context, data);
|
|
137
153
|
},
|
|
138
154
|
});
|
|
139
155
|
}
|
|
140
156
|
|
|
141
157
|
handleReserveIt() {
|
|
142
158
|
const context = 'join_waitlist';
|
|
143
|
-
this.
|
|
159
|
+
this.ActionError(context);
|
|
144
160
|
|
|
145
161
|
ActionsHandlerService({
|
|
146
162
|
action: context,
|
|
@@ -149,15 +165,14 @@ export default class ActionsHandler extends LitElement {
|
|
|
149
165
|
URLHelper.goToUrl(URLHelper.getRedirectUrl(), true);
|
|
150
166
|
},
|
|
151
167
|
error: data => {
|
|
152
|
-
|
|
153
|
-
this.toggleActionBarState(context);
|
|
168
|
+
this.ActionError(context, data);
|
|
154
169
|
},
|
|
155
170
|
});
|
|
156
171
|
}
|
|
157
172
|
|
|
158
173
|
handleRemoveFromWaitingList() {
|
|
159
174
|
const context = 'leave_waitlist';
|
|
160
|
-
this.
|
|
175
|
+
this.ActionError(context);
|
|
161
176
|
|
|
162
177
|
ActionsHandlerService({
|
|
163
178
|
action: context,
|
|
@@ -166,12 +181,31 @@ export default class ActionsHandler extends LitElement {
|
|
|
166
181
|
URLHelper.goToUrl(URLHelper.getRedirectUrl(), true);
|
|
167
182
|
},
|
|
168
183
|
error: data => {
|
|
169
|
-
|
|
170
|
-
|
|
184
|
+
this.ActionError(context, data);
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
handleLoanTokenPoller() {
|
|
190
|
+
const context = 'create_token';
|
|
191
|
+
ActionsHandlerService({
|
|
192
|
+
identifier: this.identifier,
|
|
193
|
+
action: context,
|
|
194
|
+
error: data => {
|
|
195
|
+
this.ActionError(context, data);
|
|
196
|
+
clearInterval(this.loanTokenInterval); // stop token fetch api
|
|
171
197
|
},
|
|
172
198
|
});
|
|
173
199
|
}
|
|
174
200
|
|
|
201
|
+
ActionError(context, data = {}) {
|
|
202
|
+
this.dispatchEvent(
|
|
203
|
+
new CustomEvent('lendingActionError', {
|
|
204
|
+
detail: { context, data },
|
|
205
|
+
})
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
175
209
|
handleLoginOk() {
|
|
176
210
|
/* eslint class-methods-use-this: "off" */
|
|
177
211
|
const target = `/account/login?referer=${encodeURIComponent(
|
|
@@ -183,9 +217,6 @@ export default class ActionsHandler extends LitElement {
|
|
|
183
217
|
handleReadItNow(extraParam) {
|
|
184
218
|
const currentParams = new URLSearchParams(window.location.search);
|
|
185
219
|
|
|
186
|
-
// Delete the ?q= parameter just after borrow a book. see: WEBDEV-3979
|
|
187
|
-
currentParams.delete('q');
|
|
188
|
-
|
|
189
220
|
if (extraParam) {
|
|
190
221
|
// append extraParam key-value in currentParams
|
|
191
222
|
const extraParams = new URLSearchParams(extraParam);
|
|
@@ -221,12 +252,4 @@ export default class ActionsHandler extends LitElement {
|
|
|
221
252
|
cookie += '; path=/; domain=.archive.org;';
|
|
222
253
|
document.cookie = cookie;
|
|
223
254
|
}
|
|
224
|
-
|
|
225
|
-
toggleActionBarState(context, data = {}) {
|
|
226
|
-
this.dispatchEvent(
|
|
227
|
-
new CustomEvent('toggle-action-bar-state', {
|
|
228
|
-
detail: { context, data },
|
|
229
|
-
})
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
255
|
}
|
package/src/ia-book-actions.js
CHANGED
|
@@ -7,6 +7,7 @@ import './components/collapsible-action-group.js';
|
|
|
7
7
|
import './components/book-title-bar.js';
|
|
8
8
|
import './components/text-group.js';
|
|
9
9
|
import './components/info-icon.js';
|
|
10
|
+
import './components/dialog-alert.js';
|
|
10
11
|
|
|
11
12
|
import GetLendingActions from './core/services/get-lending-actions.js';
|
|
12
13
|
import { mobileContainerWidth } from './core/config/constants.js';
|
|
@@ -22,7 +23,9 @@ export default class IABookActions extends LitElement {
|
|
|
22
23
|
bwbPurchaseUrl: { type: String },
|
|
23
24
|
barType: { type: String },
|
|
24
25
|
sharedObserver: { attribute: false },
|
|
25
|
-
|
|
26
|
+
disableActionGroup: { type: Boolean },
|
|
27
|
+
dialogVisible: { type: Boolean },
|
|
28
|
+
bookHasBrowsed: { type: Boolean },
|
|
26
29
|
};
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -41,7 +44,9 @@ export default class IABookActions extends LitElement {
|
|
|
41
44
|
this.primaryColor = 'primary';
|
|
42
45
|
this.secondaryActions = [];
|
|
43
46
|
this.lendingOptions = {};
|
|
44
|
-
this.
|
|
47
|
+
this.disableActionGroup = false;
|
|
48
|
+
this.dialogVisible = false;
|
|
49
|
+
this.bookHasBrowsed = false;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
disconnectedCallback() {
|
|
@@ -141,10 +146,12 @@ export default class IABookActions extends LitElement {
|
|
|
141
146
|
return action != null;
|
|
142
147
|
});
|
|
143
148
|
|
|
144
|
-
|
|
149
|
+
this.bookHasBrowsed =
|
|
145
150
|
this.lendingStatus.user_has_browsed &&
|
|
146
|
-
!this.lendingStatus.
|
|
147
|
-
) {
|
|
151
|
+
!this.lendingStatus.browsingExpired;
|
|
152
|
+
if (this.bookHasBrowsed) {
|
|
153
|
+
// start timer for 1-hour borrowed book.
|
|
154
|
+
// when 1 hour is completed, we shows browse-again button
|
|
148
155
|
this.startBrowseTimer();
|
|
149
156
|
}
|
|
150
157
|
}
|
|
@@ -154,9 +161,22 @@ export default class IABookActions extends LitElement {
|
|
|
154
161
|
<section class="lending-wrapper">
|
|
155
162
|
${this.barType === 'title' ? this.bookTitleBar : this.bookActionBar}
|
|
156
163
|
</section>
|
|
164
|
+
|
|
165
|
+
<show-dialog
|
|
166
|
+
.title=${this.dialogTitle}
|
|
167
|
+
.body=${this.dialogBody}
|
|
168
|
+
.actions=${this.dialogActions}
|
|
169
|
+
?opened=${this.dialogVisible}
|
|
170
|
+
?allowClose=${this.allowClose}
|
|
171
|
+
@dialogAlertClose="${() => this.closeDialogAlert()}"
|
|
172
|
+
></show-dialog>
|
|
157
173
|
`;
|
|
158
174
|
}
|
|
159
175
|
|
|
176
|
+
closeDialogAlert() {
|
|
177
|
+
this.dialogVisible = false;
|
|
178
|
+
}
|
|
179
|
+
|
|
160
180
|
get bookTitleBar() {
|
|
161
181
|
return html`<book-title-bar
|
|
162
182
|
.identifier=${this.identifier}
|
|
@@ -173,29 +193,60 @@ export default class IABookActions extends LitElement {
|
|
|
173
193
|
.primaryActions=${this.primaryActions}
|
|
174
194
|
.secondaryActions=${this.secondaryActions}
|
|
175
195
|
.width=${this.width}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
196
|
+
?hasAdminAccess=${this.hasAdminAccess}
|
|
197
|
+
?disabled=${this.disableActionGroup}
|
|
198
|
+
?bookHasBrowsed=${this.bookHasBrowsed}
|
|
199
|
+
@lendingActionError=${this.handleLendingActionError}
|
|
179
200
|
>
|
|
180
201
|
</collapsible-action-group>
|
|
181
202
|
${this.textGroupTemplate} ${this.infoIconTemplate}
|
|
182
203
|
`;
|
|
183
204
|
}
|
|
184
205
|
|
|
185
|
-
|
|
206
|
+
handleLendingActionError(e) {
|
|
186
207
|
// toggle activity loader
|
|
187
|
-
this.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
208
|
+
this.disableActionGroup = !this.disableActionGroup;
|
|
209
|
+
|
|
210
|
+
const context = e?.detail?.context;
|
|
211
|
+
const errorMsg = e?.detail?.data?.error;
|
|
212
|
+
|
|
213
|
+
// initiate dialog-alert if error occured
|
|
214
|
+
if (errorMsg) this.initializeDialogAlert(context, errorMsg);
|
|
215
|
+
|
|
216
|
+
// update action bar state if book is not available to browse or borrow.
|
|
217
|
+
if (errorMsg && errorMsg.match(/not available to borrow/gm)) {
|
|
218
|
+
let currStatus = this.lendingStatus;
|
|
219
|
+
if (context === 'browse_book') {
|
|
220
|
+
currStatus = {
|
|
221
|
+
...this.lendingStatus,
|
|
222
|
+
available_to_browse: false,
|
|
223
|
+
};
|
|
224
|
+
} else if (context === 'borrow_book') {
|
|
225
|
+
currStatus = {
|
|
226
|
+
...this.lendingStatus,
|
|
227
|
+
available_to_borrow: false,
|
|
228
|
+
};
|
|
198
229
|
}
|
|
230
|
+
this.lendingStatus = currStatus;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* set props value to show dialog alert */
|
|
235
|
+
initializeDialogAlert(context, errorMsg) {
|
|
236
|
+
this.dialogVisible = true;
|
|
237
|
+
this.dialogTitle = 'Sorry!';
|
|
238
|
+
this.dialogBody = errorMsg;
|
|
239
|
+
this.allowClose = true;
|
|
240
|
+
|
|
241
|
+
if (context === 'create_token') {
|
|
242
|
+
this.allowClose = false;
|
|
243
|
+
this.dialogActions = [
|
|
244
|
+
{
|
|
245
|
+
className: 'ia-button primary',
|
|
246
|
+
text: 'Back to Item Details',
|
|
247
|
+
href: this.lendingStatus.bookUrl,
|
|
248
|
+
},
|
|
249
|
+
];
|
|
199
250
|
}
|
|
200
251
|
}
|
|
201
252
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import { html, fixture, expect } from '@open-wc/testing';
|
|
3
|
+
import '../../src/components/dialog-alert.js';
|
|
4
|
+
|
|
5
|
+
const container = ({
|
|
6
|
+
title = '',
|
|
7
|
+
body = '',
|
|
8
|
+
allowClose = false,
|
|
9
|
+
opened = false,
|
|
10
|
+
} = {}) =>
|
|
11
|
+
html`<show-dialog
|
|
12
|
+
.title=${title}
|
|
13
|
+
.body=${body}
|
|
14
|
+
?allowClose=${allowClose}
|
|
15
|
+
?opened=${opened}
|
|
16
|
+
></show-dialog>`;
|
|
17
|
+
|
|
18
|
+
describe('<show-dialog>', () => {
|
|
19
|
+
it('assign values and initiate dialog-alert', async () => {
|
|
20
|
+
const el = await fixture(
|
|
21
|
+
container({
|
|
22
|
+
title: 'internal error!',
|
|
23
|
+
body: 'there was an internal error',
|
|
24
|
+
opened: true,
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
expect(el.title).to.be.equal('internal error!');
|
|
28
|
+
expect(el.body).to.be.equal('there was an internal error');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('close button should not render', async () => {
|
|
32
|
+
const el = await fixture(
|
|
33
|
+
container({
|
|
34
|
+
title: 'internal error!',
|
|
35
|
+
body: 'there was an internal error',
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
expect(el.title).to.be.equal('internal error!');
|
|
39
|
+
expect(el.body).to.be.equal('there was an internal error');
|
|
40
|
+
|
|
41
|
+
// close icon is not exist
|
|
42
|
+
const closeButton = el.shadowRoot.querySelector('ia-icon-close');
|
|
43
|
+
expect(closeButton).to.be.null;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('close dialog-alert on X icon click', async () => {
|
|
47
|
+
const el = await fixture(
|
|
48
|
+
container({
|
|
49
|
+
title: 'internal error!',
|
|
50
|
+
body: 'there was an internal error',
|
|
51
|
+
allowClose: true,
|
|
52
|
+
opened: true,
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const closeButton = el.shadowRoot.querySelector('ia-icon-close');
|
|
57
|
+
const errorEvent = new CustomEvent('dialogAlertClose');
|
|
58
|
+
closeButton.dispatchEvent(errorEvent);
|
|
59
|
+
await el.updateComplete;
|
|
60
|
+
expect(el.opened).to.be.true;
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -106,6 +106,64 @@ describe('Primary Actions data', () => {
|
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
describe('Borrow status actions', () => {
|
|
109
|
+
it('Update available_to_browse key when book is not available to borrow', async () => {
|
|
110
|
+
const el = await fixture(
|
|
111
|
+
container({
|
|
112
|
+
userid: '@user1',
|
|
113
|
+
lendingStatus: {
|
|
114
|
+
is_lendable: true,
|
|
115
|
+
available_to_browse: true,
|
|
116
|
+
available_to_borrow: true,
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const errorEvent = new CustomEvent('lendingActionError');
|
|
122
|
+
el.addEventListener('lendingActionError', () => {
|
|
123
|
+
el.handleLendingActionError({
|
|
124
|
+
detail: {
|
|
125
|
+
context: 'browse_book',
|
|
126
|
+
data: { error: 'not available to borrow' },
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
el.dispatchEvent(errorEvent);
|
|
131
|
+
await el.updateComplete;
|
|
132
|
+
|
|
133
|
+
// removed available_to_browse from lending bar
|
|
134
|
+
expect(el.lendingStatus.available_to_browse).to.be.false;
|
|
135
|
+
expect(el.primaryActions[0].text).to.equal('Borrow for 14 days');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('Update available_to_borrow key when book is not available to borrow', async () => {
|
|
139
|
+
const el = await fixture(
|
|
140
|
+
container({
|
|
141
|
+
userid: '@user1',
|
|
142
|
+
lendingStatus: {
|
|
143
|
+
is_lendable: true,
|
|
144
|
+
available_to_browse: true,
|
|
145
|
+
available_to_borrow: true,
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const errorEvent = new Event('lendingActionError');
|
|
151
|
+
el.addEventListener('lendingActionError', () => {
|
|
152
|
+
el.handleLendingActionError({
|
|
153
|
+
detail: {
|
|
154
|
+
context: 'borrow_book',
|
|
155
|
+
data: { error: 'not available to borrow' },
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
el.dispatchEvent(errorEvent);
|
|
160
|
+
await el.updateComplete;
|
|
161
|
+
|
|
162
|
+
// removed available_to_borrow from lending bar
|
|
163
|
+
expect(el.lendingStatus.available_to_borrow).to.be.false;
|
|
164
|
+
expect(el.primaryActions[0].text).to.equal('Borrow for 1 hour');
|
|
165
|
+
});
|
|
166
|
+
|
|
109
167
|
it('Check action for borrowable book without user', async () => {
|
|
110
168
|
const el = await fixture(
|
|
111
169
|
container({
|