@internetarchive/ia-book-actions 0.0.7-1 → 0.0.7-10
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/README.md +93 -47
- package/assets/ia-book-action-screen.png +0 -0
- package/assets/ia-book-title-screen.png +0 -0
- package/demo/index.html +7 -5
- package/package.json +2 -1
- package/src/components/collapsible-action-group.js +7 -39
- package/src/core/services/actions-handler/actions-handler-service.js +13 -12
- package/src/core/services/actions-handler/actions-handler.js +59 -68
- package/src/core/services/get-lending-actions.js +3 -3
- package/src/core/services/loan-token-poller.js +103 -0
- package/src/ia-book-actions.js +85 -53
- package/test/components/collapsible-action-group.test.js +0 -25
- package/test/ia-book-actions.test.js +2 -2
- package/src/core/services/get-realtime-lending-status.js +0 -31
package/README.md
CHANGED
|
@@ -1,69 +1,115 @@
|
|
|
1
|
-
|
|
1
|
+
# Component for lendable and embed items
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The book action button component build on LitElement with support for custom content and light DOM elements.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Usage
|
|
8
|
-
|
|
9
|
-
1. Click the "Use this Template" button in GitHub to create a new repository based on this one.
|
|
10
|
-
2. Clone your new repo and update the things below.
|
|
11
|
-
|
|
12
|
-
### Things to update in your copy
|
|
13
|
-
1. Remove this section
|
|
14
|
-
2. Search for the strings `your-webcomponent` and `YourWebComponent` and those are most of the spots that need to be updated.
|
|
15
|
-
3. `README.md` (this file). Update the readme in general, but also the badge URLs
|
|
16
|
-
4. `package.json` Update the name and description
|
|
17
|
-
5. Rename the `your-webcomponent.ts` and its associated `.test` file
|
|
18
|
-
6. Update `.travis.yml` with the proper secure key. See the [Travis docs](https://blog.travis-ci.com/2014-03-13-slack-notifications/) for more information.
|
|
19
|
-
|
|
20
|
-
## Local Demo with `web-dev-server`
|
|
5
|
+
## Installation
|
|
21
6
|
```bash
|
|
22
|
-
yarn
|
|
7
|
+
yarn install --save @internetarchive/ia-book-actions
|
|
23
8
|
```
|
|
24
|
-
To run a local development server that serves the basic demo located in `demo/index.html`
|
|
25
9
|
|
|
26
|
-
##
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
## Usage of Book Actions
|
|
11
|
+
```html
|
|
12
|
+
<!-- index.html -->
|
|
13
|
+
<style>
|
|
14
|
+
html {
|
|
15
|
+
font-size: 10px;
|
|
16
|
+
/* This is to match petabox's base font size */
|
|
17
|
+
}
|
|
18
|
+
body {
|
|
19
|
+
margin: 0;
|
|
20
|
+
text-align: center;
|
|
21
|
+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
22
|
+
}
|
|
23
|
+
#demo {
|
|
24
|
+
height: 50px;
|
|
25
|
+
}
|
|
26
|
+
ia-book-actions {
|
|
27
|
+
--white: #fff;
|
|
28
|
+
--black: #000;
|
|
29
|
+
--primaryBGColor: var(--black);
|
|
30
|
+
--secondaryBGColor: #222;
|
|
31
|
+
--tertiaryBGColor: #333;
|
|
32
|
+
--primaryTextColor: var(--white);
|
|
33
|
+
--primaryCTAFill: #194880;
|
|
34
|
+
--primaryCTABorder: #c5d1df;
|
|
35
|
+
--secondaryCTAFill: #333;
|
|
36
|
+
--secondaryCTABorder: #999;
|
|
37
|
+
--secondaryCTAFillRGB: 51, 51, 51;
|
|
38
|
+
--primaryErrorCTAFill: #e51c26;
|
|
39
|
+
--primaryErrorCTABorder: #f8c6c8;
|
|
40
|
+
--primaryCTAFillRGB: 25, 72, 128;
|
|
41
|
+
--primaryErrorCTAFillRGB: 229, 28, 38;
|
|
42
|
+
--primaryDisableCTAFill: #767676;
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
45
|
+
|
|
46
|
+
<ia-book-actions></ia-book-actions>
|
|
47
|
+
|
|
48
|
+
<script type="module">
|
|
49
|
+
import '@internetarchive/ia-book-actions.js';
|
|
50
|
+
import { ModalConfig } from '@internetarchive/modal-manager';
|
|
51
|
+
import {
|
|
52
|
+
defaultLendingStatus,
|
|
53
|
+
canBrowseAndBorrow,
|
|
54
|
+
} from '../src/assets/data/lending-get-status-service.js';
|
|
55
|
+
|
|
56
|
+
let iaBookActions = document.querySelector('ia-book-actions');
|
|
57
|
+
iaBookActions.userid = '@neeraj-archive';
|
|
58
|
+
iaBookActions.identifier = 'naturalhistoryof00unse_4111';
|
|
59
|
+
iaBookActions.bookTitle = 'This is test title for any book';
|
|
60
|
+
iaBookActions.lendingStatus = {}; // lendinStatus in json
|
|
61
|
+
iaBookActions.bwbPurchaseUrl = 'https://bwb.com/produce/123';
|
|
62
|
+
iaBookActions.barType = ''; // title|action
|
|
63
|
+
</script>
|
|
30
64
|
```
|
|
31
65
|
|
|
32
|
-
|
|
66
|
+

|
|
33
67
|
|
|
34
|
-
|
|
35
|
-
|
|
68
|
+
## Usage of Book Title
|
|
69
|
+
```html
|
|
70
|
+
<!-- along with above properties, set barType to 'title' -->
|
|
71
|
+
<script type="module">
|
|
72
|
+
iaBookActions.barType = 'title'; // title|action
|
|
73
|
+
</script>
|
|
36
74
|
```
|
|
75
|
+

|
|
37
76
|
|
|
38
|
-
|
|
39
|
-
To scan the project for linting errors, run
|
|
40
|
-
```bash
|
|
41
|
-
yarn run lint
|
|
42
|
-
```
|
|
77
|
+
### Config Options
|
|
43
78
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
79
|
+
All of the config options:
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
let iaBookActions = document.querySelector('ia-book-actions');
|
|
83
|
+
const modalConfig = new ModalConfig(); // to show info/error modal
|
|
84
|
+
|
|
85
|
+
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
86
|
+
iaBookActions.userid = '@jack';
|
|
87
|
+
iaBookActions.identifier = 'jack-sparrow';
|
|
88
|
+
iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
|
|
89
|
+
iaBookActions.lendingStatus = {active_borrows: 0, active_browses: 0}, // complete lendingStatus object
|
|
90
|
+
iaBookActions.bwbPurchaseUrl = ''; // BWB purchase URl if any
|
|
91
|
+
iaBookActions.barType = '';
|
|
92
|
+
iaBookActions.modalConfig = modalConfig;
|
|
47
93
|
```
|
|
94
|
+
|
|
95
|
+
# Development
|
|
96
|
+
|
|
97
|
+
## Prerequisite
|
|
48
98
|
```bash
|
|
49
|
-
yarn
|
|
99
|
+
yarn install
|
|
50
100
|
```
|
|
51
101
|
|
|
52
|
-
|
|
102
|
+
## Start Development Server
|
|
53
103
|
```bash
|
|
54
|
-
yarn
|
|
104
|
+
yarn start
|
|
55
105
|
```
|
|
56
106
|
|
|
57
|
-
|
|
107
|
+
## Testing
|
|
58
108
|
```bash
|
|
59
|
-
yarn
|
|
109
|
+
yarn test
|
|
60
110
|
```
|
|
111
|
+
|
|
112
|
+
## Linting
|
|
61
113
|
```bash
|
|
62
|
-
yarn
|
|
114
|
+
yarn lint
|
|
63
115
|
```
|
|
64
|
-
|
|
65
|
-
## Tooling configs
|
|
66
|
-
|
|
67
|
-
For most of the tools, the configuration is in the `package.json` to reduce the amount of files in your project.
|
|
68
|
-
|
|
69
|
-
If you customize the configuration a lot, you can consider moving them to individual files.
|
|
Binary file
|
|
Binary file
|
package/demo/index.html
CHANGED
|
@@ -76,13 +76,9 @@
|
|
|
76
76
|
overflow: hidden;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
modal-manager {
|
|
79
|
+
modal-manager[mode='closed'] {
|
|
80
80
|
display: none;
|
|
81
81
|
}
|
|
82
|
-
|
|
83
|
-
modal-manager[mode='open'] {
|
|
84
|
-
display: block;
|
|
85
|
-
}
|
|
86
82
|
</style>
|
|
87
83
|
</head>
|
|
88
84
|
|
|
@@ -108,6 +104,11 @@
|
|
|
108
104
|
const modalConfig = new ModalConfig();
|
|
109
105
|
modalConfig.headerColor = '#d9534f';
|
|
110
106
|
|
|
107
|
+
let lendingBarPostInit = function lendingBarPostInit() {
|
|
108
|
+
setTimeout(function() {
|
|
109
|
+
console.log('executed');
|
|
110
|
+
}, 100);
|
|
111
|
+
}
|
|
111
112
|
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
112
113
|
iaBookActions.userid = userid;
|
|
113
114
|
iaBookActions.identifier = identifier;
|
|
@@ -116,6 +117,7 @@
|
|
|
116
117
|
iaBookActions.bwbPurchaseUrl = '';
|
|
117
118
|
iaBookActions.barType = '';
|
|
118
119
|
iaBookActions.modalConfig = modalConfig;
|
|
120
|
+
iaBookActions.lendingBarPostInit = lendingBarPostInit;
|
|
119
121
|
|
|
120
122
|
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
121
123
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "0.0.7-
|
|
3
|
+
"version": "0.0.7-10",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"@internetarchive/icon-bookmark": "^1.1.3",
|
|
23
23
|
"@internetarchive/icon-close": "^1.1.3",
|
|
24
24
|
"@internetarchive/icon-info": "^1.2.6",
|
|
25
|
+
"@internetarchive/local-cache": "^0.2.0",
|
|
25
26
|
"@internetarchive/modal-manager": "^0.1.0",
|
|
26
27
|
"@internetarchive/shared-resize-observer": "^0.0.1",
|
|
27
28
|
"lit-element": "^2.4.0",
|
|
@@ -27,7 +27,6 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
27
27
|
hasAdminAccess: { type: Boolean },
|
|
28
28
|
dropdownArrow: { type: String },
|
|
29
29
|
disabled: { type: Boolean },
|
|
30
|
-
borrowType: { type: String },
|
|
31
30
|
};
|
|
32
31
|
}
|
|
33
32
|
|
|
@@ -46,45 +45,12 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
46
45
|
this.title = '';
|
|
47
46
|
this.loaderIcon = 'https://archive.org/upload/images/tree/loading.gif';
|
|
48
47
|
this.disabled = false;
|
|
49
|
-
this.borrowType = ''; // (browsed|borrowed)
|
|
50
|
-
this.consecutiveLoanCounts = 1; // consecutive loan count
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
updated(changed) {
|
|
54
|
-
if (changed.has('width')) {
|
|
55
|
-
|
|
56
|
-
this.resetActions();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// this is execute to fetch loan token
|
|
61
|
-
if (changed.has('borrowType')) {
|
|
62
|
-
this.emitEnableBookAccess();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/* emit custom event to fetch loan token */
|
|
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;
|
|
51
|
+
if (changed.has('width') && this.isBelowTabletContainer) {
|
|
52
|
+
this.resetActions();
|
|
73
53
|
}
|
|
74
|
-
|
|
75
|
-
this.dispatchEvent(
|
|
76
|
-
new CustomEvent('enableBookAccess', {
|
|
77
|
-
detail: {
|
|
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,
|
|
85
|
-
},
|
|
86
|
-
})
|
|
87
|
-
);
|
|
88
54
|
}
|
|
89
55
|
|
|
90
56
|
/**
|
|
@@ -219,11 +185,13 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
219
185
|
}
|
|
220
186
|
|
|
221
187
|
/**
|
|
222
|
-
*
|
|
223
|
-
* @param { string } eventName
|
|
224
|
-
* @param { object } gaEvent
|
|
188
|
+
* Dispatches click events when patron clicks on action buttons
|
|
189
|
+
* @param { string } eventName - actions like 'browseBook', 'borrowBook' etc...
|
|
190
|
+
* @param { object } gaEvent - contains analytics event action and category
|
|
225
191
|
* @param { string } gaEvent.category
|
|
226
192
|
* @param { string } gaEvent.action
|
|
193
|
+
*
|
|
194
|
+
* @fires CollapsibleActionGroup#{eventName} - (will be browseBook, borrowBook etc...)
|
|
227
195
|
*/
|
|
228
196
|
clickHandler(eventName, gaEvent) {
|
|
229
197
|
this.dropdownState = 'close';
|
|
@@ -13,12 +13,15 @@ export default function ActionsHandlerService(options) {
|
|
|
13
13
|
...options,
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
let baseHost = '';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
let baseHost = '/services/loans/loan';
|
|
17
|
+
const location = window?.location;
|
|
18
|
+
|
|
19
|
+
// return intentional error on dev environment
|
|
20
|
+
const shouldReturnError =
|
|
21
|
+
location?.href?.indexOf('?error=true') !== -1 &&
|
|
22
|
+
location?.hostname !== 'archive.org';
|
|
23
|
+
|
|
24
|
+
if (location?.pathname === '/demo/') baseHost = `/demo/`;
|
|
22
25
|
|
|
23
26
|
let formData = new FormData();
|
|
24
27
|
formData.append('action', option.action);
|
|
@@ -29,18 +32,16 @@ export default function ActionsHandlerService(options) {
|
|
|
29
32
|
body: formData,
|
|
30
33
|
})
|
|
31
34
|
.then(response => {
|
|
32
|
-
let shouldReturnError =
|
|
33
|
-
window.location.href.indexOf('?error=true') !== -1;
|
|
34
35
|
const tokenError = 'loan token not found. please try again later.';
|
|
35
36
|
const borrowError =
|
|
36
37
|
'This book is not available to borrow at this time. Please try again later.';
|
|
37
38
|
|
|
38
|
-
// return error reponse
|
|
39
|
+
// return error reponse when not production and has ?error=true param...
|
|
39
40
|
const erroneousActions = ['browse_book', 'borrow_book', 'create_token'];
|
|
40
|
-
if (shouldReturnError && erroneousActions.includes(option
|
|
41
|
+
if (shouldReturnError && erroneousActions.includes(option?.action)) {
|
|
41
42
|
return {
|
|
42
43
|
success: false,
|
|
43
|
-
error: option
|
|
44
|
+
error: option?.action === 'create_token' ? tokenError : borrowError,
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -58,7 +59,7 @@ export default function ActionsHandlerService(options) {
|
|
|
58
59
|
})
|
|
59
60
|
.then(data => {
|
|
60
61
|
// `data` is the parsed version of the JSON returned from the above endpoint.
|
|
61
|
-
if (!data
|
|
62
|
+
if (!data?.error) {
|
|
62
63
|
option?.success(data);
|
|
63
64
|
} else {
|
|
64
65
|
option?.error(data);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { LitElement } from 'lit-element';
|
|
2
|
+
import { LocalCache } from '@internetarchive/local-cache';
|
|
3
|
+
|
|
2
4
|
import { URLHelper } from '../../config/url-helper.js';
|
|
3
5
|
import ActionsHandlerService from './actions-handler-service.js';
|
|
4
6
|
|
|
@@ -14,17 +16,11 @@ export default class ActionsHandler extends LitElement {
|
|
|
14
16
|
constructor(identifier) {
|
|
15
17
|
super();
|
|
16
18
|
this.identifier = identifier;
|
|
17
|
-
this.ajaxTimeout =
|
|
18
|
-
this.
|
|
19
|
-
window.location.pathname === '/demo/' ? 2000 : 120000; // 120000 ms = 2 min
|
|
20
|
-
this.loanTokenInterval = null;
|
|
19
|
+
this.ajaxTimeout = 7000;
|
|
20
|
+
this.localCache = new LocalCache();
|
|
21
21
|
this.bindEvents();
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
disconnectedCallback() {
|
|
25
|
-
this.loanTokenInterval = undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
24
|
sendEvent(eventCategory, eventAction) {
|
|
29
25
|
// eslint-disable-next-line no-console
|
|
30
26
|
console?.log('Book action: ', { eventCategory, eventAction });
|
|
@@ -99,128 +95,117 @@ export default class ActionsHandler extends LitElement {
|
|
|
99
95
|
const { category, action } = detail.event;
|
|
100
96
|
this.sendEvent(category, action);
|
|
101
97
|
});
|
|
102
|
-
|
|
103
|
-
this.addEventListener('enableBookAccess', ({ detail }) => {
|
|
104
|
-
const borrowType = detail?.borrowType;
|
|
105
|
-
|
|
106
|
-
// fetch loan token for browsed/borrowed book and set an interval
|
|
107
|
-
if (borrowType) {
|
|
108
|
-
console.log('token poll started...');
|
|
109
|
-
|
|
110
|
-
this.loanTokenInterval = setInterval(() => {
|
|
111
|
-
this.handleLoanTokenPoller();
|
|
112
|
-
}, this.loanTokenPollingDelay);
|
|
113
|
-
|
|
114
|
-
const { category, action } = detail?.event;
|
|
115
|
-
this.sendEvent(category, action);
|
|
116
|
-
} else {
|
|
117
|
-
// if book is not browsed, just clear token polling interval
|
|
118
|
-
clearInterval(this.loanTokenInterval);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
98
|
}
|
|
122
99
|
|
|
123
100
|
handleBrowseIt() {
|
|
124
|
-
const
|
|
125
|
-
this.
|
|
101
|
+
const action = 'browse_book';
|
|
102
|
+
this.dispatchToggleActionGroup();
|
|
126
103
|
|
|
127
104
|
ActionsHandlerService({
|
|
128
|
-
action
|
|
105
|
+
action,
|
|
129
106
|
identifier: this.identifier,
|
|
130
107
|
success: () => {
|
|
131
108
|
this.handleReadItNow();
|
|
132
109
|
},
|
|
133
110
|
error: data => {
|
|
134
|
-
this.
|
|
111
|
+
this.dispatchActionError(action, data);
|
|
135
112
|
},
|
|
136
113
|
});
|
|
137
114
|
}
|
|
138
115
|
|
|
139
116
|
handleReturnIt() {
|
|
140
|
-
const
|
|
141
|
-
this.
|
|
117
|
+
const action = 'return_loan';
|
|
118
|
+
this.dispatchToggleActionGroup();
|
|
142
119
|
|
|
143
120
|
ActionsHandlerService({
|
|
144
|
-
action
|
|
121
|
+
action,
|
|
145
122
|
identifier: this.identifier,
|
|
146
123
|
success: () => {
|
|
147
124
|
this.deleteLoanCookies();
|
|
148
125
|
URLHelper.goToUrl(`/details/${this.identifier}`, true);
|
|
149
126
|
},
|
|
150
127
|
error: data => {
|
|
151
|
-
this.
|
|
128
|
+
this.dispatchActionError(action, data);
|
|
152
129
|
},
|
|
153
130
|
});
|
|
154
131
|
}
|
|
155
132
|
|
|
156
133
|
handleBorrowIt() {
|
|
157
|
-
const
|
|
158
|
-
this.
|
|
134
|
+
const action = 'borrow_book';
|
|
135
|
+
this.dispatchToggleActionGroup();
|
|
159
136
|
|
|
160
137
|
ActionsHandlerService({
|
|
161
|
-
action
|
|
138
|
+
action,
|
|
162
139
|
identifier: this.identifier,
|
|
163
140
|
success: () => {
|
|
164
141
|
this.handleReadItNow();
|
|
165
142
|
},
|
|
166
143
|
error: data => {
|
|
167
|
-
this.
|
|
144
|
+
this.dispatchActionError(action, data);
|
|
168
145
|
},
|
|
169
146
|
});
|
|
170
147
|
}
|
|
171
148
|
|
|
172
149
|
handleReserveIt() {
|
|
173
|
-
const
|
|
174
|
-
this.
|
|
150
|
+
const action = 'join_waitlist';
|
|
151
|
+
this.dispatchToggleActionGroup();
|
|
175
152
|
|
|
176
153
|
ActionsHandlerService({
|
|
177
|
-
action
|
|
154
|
+
action,
|
|
178
155
|
identifier: this.identifier,
|
|
179
156
|
success: () => {
|
|
180
157
|
URLHelper.goToUrl(URLHelper.getRedirectUrl(), true);
|
|
181
158
|
},
|
|
182
159
|
error: data => {
|
|
183
|
-
this.
|
|
160
|
+
this.dispatchActionError(action, data);
|
|
184
161
|
},
|
|
185
162
|
});
|
|
186
163
|
}
|
|
187
164
|
|
|
188
165
|
handleRemoveFromWaitingList() {
|
|
189
|
-
const
|
|
190
|
-
this.
|
|
166
|
+
const action = 'leave_waitlist';
|
|
167
|
+
this.dispatchToggleActionGroup();
|
|
191
168
|
|
|
192
169
|
ActionsHandlerService({
|
|
193
|
-
action
|
|
170
|
+
action,
|
|
194
171
|
identifier: this.identifier,
|
|
195
172
|
success: () => {
|
|
196
173
|
URLHelper.goToUrl(URLHelper.getRedirectUrl(), true);
|
|
197
174
|
},
|
|
198
175
|
error: data => {
|
|
199
|
-
this.
|
|
176
|
+
this.dispatchActionError(action, data);
|
|
200
177
|
},
|
|
201
178
|
});
|
|
202
179
|
}
|
|
203
180
|
|
|
204
|
-
handleLoanTokenPoller() {
|
|
205
|
-
const context = 'create_token';
|
|
206
|
-
ActionsHandlerService({
|
|
207
|
-
identifier: this.identifier,
|
|
208
|
-
action: context,
|
|
209
|
-
error: data => {
|
|
210
|
-
this.ActionError(context, data);
|
|
211
|
-
clearInterval(this.loanTokenInterval); // stop token fetch api
|
|
212
|
-
},
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
181
|
|
|
216
|
-
|
|
182
|
+
/**
|
|
183
|
+
* Dispatches event when an error occured on action
|
|
184
|
+
* Notes:- toggle <collapsible-action-group> visibility (enable/disable).
|
|
185
|
+
*
|
|
186
|
+
* @param { String } action - name of action like browse_book, borrow_book
|
|
187
|
+
* @param { Object } data - erroneous response from api call
|
|
188
|
+
*
|
|
189
|
+
* @fires ActionsHandler#lendingActionError
|
|
190
|
+
*/
|
|
191
|
+
dispatchActionError(action, data = {}) {
|
|
217
192
|
this.dispatchEvent(
|
|
218
193
|
new CustomEvent('lendingActionError', {
|
|
219
|
-
detail: {
|
|
194
|
+
detail: { action, data },
|
|
220
195
|
})
|
|
221
196
|
);
|
|
222
197
|
}
|
|
223
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Dispatches event when patron is clicked on action buttons.
|
|
201
|
+
* Notes:- toggle <collapsible-action-group> disable/enable.
|
|
202
|
+
*
|
|
203
|
+
* @fires ActionsHandler#toggleActionGroup
|
|
204
|
+
*/
|
|
205
|
+
dispatchToggleActionGroup() {
|
|
206
|
+
this.dispatchEvent(new CustomEvent('toggleActionGroup'));
|
|
207
|
+
}
|
|
208
|
+
|
|
224
209
|
handleLoginOk() {
|
|
225
210
|
/* eslint class-methods-use-this: "off" */
|
|
226
211
|
const target = `/account/login?referer=${encodeURIComponent(
|
|
@@ -254,19 +239,25 @@ export default class ActionsHandler extends LitElement {
|
|
|
254
239
|
}
|
|
255
240
|
|
|
256
241
|
// save consecutive loan count for borrow
|
|
257
|
-
setConsecutiveLoanCounts(action = '') {
|
|
258
|
-
|
|
259
|
-
if (localStorage) {
|
|
242
|
+
async setConsecutiveLoanCounts(action = '') {
|
|
243
|
+
try {
|
|
260
244
|
let newCount = 1;
|
|
261
245
|
const storageKey = `consecutive-loan-count`;
|
|
262
|
-
const existingCount =
|
|
246
|
+
const existingCount = await this.localCache.get(storageKey);
|
|
263
247
|
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
if (action === 'browseAgain') {
|
|
248
|
+
// increase browse-count by 1 when you consecutive reading a book.
|
|
249
|
+
if (action === 'browseAgain' && existingCount !== undefined) {
|
|
267
250
|
newCount = existingCount ? existingCount + 1 : 1;
|
|
268
251
|
}
|
|
269
|
-
|
|
252
|
+
|
|
253
|
+
// set new value
|
|
254
|
+
await this.localCache.set({
|
|
255
|
+
key: storageKey,
|
|
256
|
+
value: newCount,
|
|
257
|
+
ttl: 7200, // 2 hours
|
|
258
|
+
});
|
|
259
|
+
} catch (error) {
|
|
260
|
+
console.log(error);
|
|
270
261
|
}
|
|
271
262
|
}
|
|
272
263
|
|
|
@@ -75,9 +75,9 @@ export default class GetLendingActions {
|
|
|
75
75
|
const disableBorrow = lendingStatus.loanCount >= lendingStatus.maxLoans;
|
|
76
76
|
|
|
77
77
|
let primaryTitleText = '';
|
|
78
|
-
let
|
|
78
|
+
let isBrowsing =
|
|
79
79
|
lendingStatus.user_has_browsed && !lendingStatus.browsingExpired;
|
|
80
|
-
if (
|
|
80
|
+
if (isBrowsing) {
|
|
81
81
|
primaryTitleText = this.getBrowseCountdownTitle();
|
|
82
82
|
} else {
|
|
83
83
|
primaryTitleText = `Your loan of this book has ${lendingStatus.daysLeftOnLoan} days left.`;
|
|
@@ -96,7 +96,7 @@ export default class GetLendingActions {
|
|
|
96
96
|
this.actionsConfig.adminAccessConfig(),
|
|
97
97
|
this.actionsConfig.purchaseConfig(),
|
|
98
98
|
],
|
|
99
|
-
borrowType:
|
|
99
|
+
borrowType: isBrowsing ? 'browsed' : 'borrowed',
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { LitElement } from 'lit-element';
|
|
2
|
+
import { LocalCache } from '@internetarchive/local-cache';
|
|
3
|
+
|
|
4
|
+
import ActionsHandlerService from './actions-handler/actions-handler-service.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This class is used to create loan token for borrowed books
|
|
8
|
+
*
|
|
9
|
+
* ActionsHandlerService is a function being used to execute
|
|
10
|
+
*/
|
|
11
|
+
export class LoanTokenPoller extends LitElement {
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
this.identifier = '';
|
|
15
|
+
this.loanTokenPollingDelay = window.location.pathname === '/demo/' ? 2000 : 120000; // 120000 ms = 2 min
|
|
16
|
+
this.loanTokenInterval = undefined;
|
|
17
|
+
this.localCache = new LocalCache();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
disconnectedCallback() {
|
|
21
|
+
this.loanTokenInterval = undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async enableBookAccess(identifier, borrowType) {
|
|
25
|
+
this.identifier = identifier
|
|
26
|
+
let consecutiveLoanCounts = 1;
|
|
27
|
+
|
|
28
|
+
if (borrowType) {
|
|
29
|
+
// send consecutiveLoanCounts for browsed books only.
|
|
30
|
+
if (borrowType === 'browsed') {
|
|
31
|
+
try {
|
|
32
|
+
const existingCount = await this.localCache.get(
|
|
33
|
+
'consecutive-loan-count'
|
|
34
|
+
);
|
|
35
|
+
consecutiveLoanCounts = existingCount ?? 1;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.log(error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Do an initial token, then set an interval
|
|
42
|
+
this.handleLoanTokenPoller();
|
|
43
|
+
|
|
44
|
+
this.loanTokenInterval = setInterval(() => {
|
|
45
|
+
this.handleLoanTokenPoller();
|
|
46
|
+
}, this.loanTokenPollingDelay);
|
|
47
|
+
|
|
48
|
+
// event category and action for browsing book access
|
|
49
|
+
const category = `${borrowType}BookAccess`;
|
|
50
|
+
const action = `${
|
|
51
|
+
borrowType === 'browsed' ? 'BrowseCounts-' : 'Counts-'
|
|
52
|
+
}${consecutiveLoanCounts}`;
|
|
53
|
+
console.log(consecutiveLoanCounts)
|
|
54
|
+
this.sendEvent(category, action);
|
|
55
|
+
} else {
|
|
56
|
+
// if book is not browsed, just clear token polling interval
|
|
57
|
+
clearInterval(this.loanTokenInterval);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
sendEvent(eventCategory, eventAction) {
|
|
62
|
+
// eslint-disable-next-line no-console
|
|
63
|
+
console?.log('Book action: ', { eventCategory, eventAction });
|
|
64
|
+
window?.archive_analytics?.send_event_no_sampling(
|
|
65
|
+
eventCategory,
|
|
66
|
+
eventAction,
|
|
67
|
+
`identifier=${this.identifier}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async handleLoanTokenPoller() {
|
|
72
|
+
const action = 'create_token';
|
|
73
|
+
// await new Promise(r => setTimeout(r, 3000));
|
|
74
|
+
ActionsHandlerService({
|
|
75
|
+
identifier: this.identifier,
|
|
76
|
+
action,
|
|
77
|
+
error: data => {
|
|
78
|
+
console.log('error', data);
|
|
79
|
+
this.handleLendingActionError({detail: { action, data }})
|
|
80
|
+
// this.dispatchActionError(action, data);
|
|
81
|
+
clearInterval(this.loanTokenInterval); // stop token fetch api
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Dispatches event when an error occured on action
|
|
88
|
+
* Notes:- toggle <collapsible-action-group> visibility (enable/disable).
|
|
89
|
+
*
|
|
90
|
+
* @param { String } action - name of action like browse_book, borrow_book
|
|
91
|
+
* @param { Object } data - erroneous response from api call
|
|
92
|
+
*
|
|
93
|
+
* @fires ActionsHandler#lendingActionError
|
|
94
|
+
*/
|
|
95
|
+
dispatchActionError(action, data = {}) {
|
|
96
|
+
console.log('disptaced');
|
|
97
|
+
this.dispatchEvent(
|
|
98
|
+
new CustomEvent('lendingActionError', {
|
|
99
|
+
detail: { action, data },
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/ia-book-actions.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable camelcase */
|
|
2
|
-
import { html, css
|
|
2
|
+
import { html, css } from 'lit-element';
|
|
3
3
|
|
|
4
4
|
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
|
5
5
|
import { ModalConfig } from '@internetarchive/modal-manager';
|
|
@@ -10,11 +10,10 @@ import './components/text-group.js';
|
|
|
10
10
|
import './components/info-icon.js';
|
|
11
11
|
|
|
12
12
|
import GetLendingActions from './core/services/get-lending-actions.js';
|
|
13
|
-
import getRealTimeLendingStatus from './core/services/get-realtime-lending-status.js';
|
|
14
|
-
|
|
15
13
|
import { mobileContainerWidth } from './core/config/constants.js';
|
|
14
|
+
import { LoanTokenPoller } from './core/services/loan-token-poller.js';
|
|
16
15
|
|
|
17
|
-
export default class IABookActions extends
|
|
16
|
+
export default class IABookActions extends LoanTokenPoller {
|
|
18
17
|
static get properties() {
|
|
19
18
|
return {
|
|
20
19
|
userid: { type: String },
|
|
@@ -23,10 +22,11 @@ export default class IABookActions extends LitElement {
|
|
|
23
22
|
lendingStatus: { type: Object },
|
|
24
23
|
width: { type: Number },
|
|
25
24
|
bwbPurchaseUrl: { type: String },
|
|
25
|
+
lendingBarPostInit: { type: Function },
|
|
26
26
|
barType: { type: String },
|
|
27
27
|
sharedObserver: { attribute: false },
|
|
28
28
|
disableActionGroup: { type: Boolean },
|
|
29
|
-
|
|
29
|
+
modal: { Object },
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -38,16 +38,20 @@ export default class IABookActions extends LitElement {
|
|
|
38
38
|
this.lendingStatus = {};
|
|
39
39
|
this.width = 0;
|
|
40
40
|
this.bwbPurchaseUrl = '';
|
|
41
|
+
this.lendingBarPostInit = () => {};
|
|
41
42
|
this.barType = 'action'; // 'title'|'action'
|
|
42
43
|
this.sharedObserver = undefined;
|
|
44
|
+
this.disableActionGroup = false;
|
|
45
|
+
this.modal = undefined;
|
|
46
|
+
|
|
47
|
+
// private props
|
|
43
48
|
this.primaryActions = [];
|
|
44
49
|
this.primaryTitle = '';
|
|
45
50
|
this.primaryColor = 'primary';
|
|
46
51
|
this.secondaryActions = [];
|
|
47
52
|
this.lendingOptions = {};
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
50
|
-
this.realtimeInternal = 0; // store intervalID
|
|
53
|
+
this.borrowType = ''; // (browsed|borrowed)
|
|
54
|
+
this.consecutiveLoanCounts = 1; // consecutive loan count
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
disconnectedCallback() {
|
|
@@ -59,29 +63,10 @@ export default class IABookActions extends LitElement {
|
|
|
59
63
|
this.sharedObserver = new SharedResizeObserver();
|
|
60
64
|
this.setupResizeObserver();
|
|
61
65
|
}
|
|
62
|
-
|
|
63
|
-
if (!Object.keys(this.modalConfig).length) {
|
|
64
|
-
this.modalConfig = new ModalConfig();
|
|
65
|
-
this.modalConfig.headerColor = '#d9534f';
|
|
66
|
-
}
|
|
67
|
-
this.setupLendingToolbarActions();
|
|
68
|
-
|
|
69
|
-
// fetch latest lending status after an internal
|
|
70
|
-
if (
|
|
71
|
-
this.lendingStatus.user_has_browsed ||
|
|
72
|
-
this.lendingStatus.user_has_borrowed
|
|
73
|
-
) {
|
|
74
|
-
this.realtimeInternal = setInterval(() => {
|
|
75
|
-
const latestLendingStatus = getRealTimeLendingStatus(
|
|
76
|
-
'naturalhistoryof00unse_4'
|
|
77
|
-
);
|
|
78
|
-
console.log(latestLendingStatus);
|
|
79
|
-
if (latestLendingStatus) this.lendingStatus = latestLendingStatus;
|
|
80
|
-
}, 30000); // 60000 ms = 1 min
|
|
81
|
-
}
|
|
82
66
|
}
|
|
83
67
|
|
|
84
68
|
updated(changed) {
|
|
69
|
+
console.log(changed)
|
|
85
70
|
if (changed.has('lendingStatus') || changed.has('bwbPurchaseUrl')) {
|
|
86
71
|
this.setupLendingToolbarActions();
|
|
87
72
|
this.update();
|
|
@@ -172,14 +157,28 @@ export default class IABookActions extends LitElement {
|
|
|
172
157
|
// when browse is completed, we shows browse-again button
|
|
173
158
|
this.startBrowseTimer();
|
|
174
159
|
}
|
|
160
|
+
|
|
161
|
+
console.log('this.borrowType', this.borrowType);
|
|
162
|
+
// enable access of borrowed/browsed books
|
|
163
|
+
if (this.borrowType) {
|
|
164
|
+
await this.enableBookAccess(this.identifier, this.borrowType);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* this callback function use to:-
|
|
169
|
+
* - disptach lenfingFlow::PostInit event
|
|
170
|
+
* - initialize bookreader using br.init()
|
|
171
|
+
*/
|
|
172
|
+
console.log(this.lendingBarPostInit);
|
|
173
|
+
this.lendingBarPostInit();
|
|
175
174
|
}
|
|
176
175
|
|
|
177
176
|
render() {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
if (this.barType === 'title') {
|
|
178
|
+
return html`<section class="lending-wrapper">${this.bookTitleBar}</section>`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return html`<section class="lending-wrapper">${this.bookActionBar}</section>`;
|
|
183
182
|
}
|
|
184
183
|
|
|
185
184
|
get bookTitleBar() {
|
|
@@ -202,6 +201,7 @@ export default class IABookActions extends LitElement {
|
|
|
202
201
|
?hasAdminAccess=${this.hasAdminAccess}
|
|
203
202
|
?disabled=${this.disableActionGroup}
|
|
204
203
|
@lendingActionError=${this.handleLendingActionError}
|
|
204
|
+
@toggleActionGroup=${this.handleToggleActionGroup}
|
|
205
205
|
>
|
|
206
206
|
</collapsible-action-group>
|
|
207
207
|
${this.textGroupTemplate} ${this.infoIconTemplate}
|
|
@@ -209,27 +209,41 @@ export default class IABookActions extends LitElement {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
/*
|
|
212
|
-
*
|
|
212
|
+
* custom event handler to toggle action group visibility
|
|
213
|
+
*
|
|
214
|
+
* @event IABookActions#toggleActionGroup
|
|
215
|
+
*/
|
|
216
|
+
handleToggleActionGroup() {
|
|
217
|
+
this.disableActionGroup = !this.disableActionGroup;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/*
|
|
221
|
+
* handle lending errors occure during different operation like
|
|
213
222
|
* browse book, borrow book, borrowed book token etc...
|
|
223
|
+
*
|
|
224
|
+
* @event IABookActions#lendingActionError
|
|
225
|
+
* @param {Object} event - The employee who is responsible for the project
|
|
226
|
+
* @param {string} event.detail.action - action when error occurred like 'browseBook', 'borrowBook'
|
|
227
|
+
* @param {string} event.detail.data.error - error message
|
|
214
228
|
*/
|
|
215
|
-
handleLendingActionError(
|
|
229
|
+
handleLendingActionError(event) {
|
|
216
230
|
// toggle activity loader
|
|
217
|
-
this.
|
|
231
|
+
this.handleToggleActionGroup();
|
|
218
232
|
|
|
219
|
-
const
|
|
220
|
-
const errorMsg =
|
|
233
|
+
const action = event?.detail?.action;
|
|
234
|
+
const errorMsg = event?.detail?.data?.error;
|
|
221
235
|
|
|
222
|
-
if (errorMsg) this.showErrorModal(
|
|
236
|
+
if (errorMsg) this.showErrorModal(errorMsg, action);
|
|
223
237
|
|
|
224
238
|
// update action bar state if book is not available to browse or borrow.
|
|
225
239
|
if (errorMsg && errorMsg.match(/not available to borrow/gm)) {
|
|
226
240
|
let currStatus = this.lendingStatus;
|
|
227
|
-
if (
|
|
241
|
+
if (action === 'browse_book') {
|
|
228
242
|
currStatus = {
|
|
229
243
|
...this.lendingStatus,
|
|
230
244
|
available_to_browse: false,
|
|
231
245
|
};
|
|
232
|
-
} else if (
|
|
246
|
+
} else if (action === 'borrow_book') {
|
|
233
247
|
currStatus = {
|
|
234
248
|
...this.lendingStatus,
|
|
235
249
|
available_to_borrow: false,
|
|
@@ -240,24 +254,42 @@ export default class IABookActions extends LitElement {
|
|
|
240
254
|
}
|
|
241
255
|
|
|
242
256
|
/* show error message if something went wrong */
|
|
243
|
-
async showErrorModal(
|
|
244
|
-
|
|
245
|
-
this.modal = document.createElement('modal-manager');
|
|
246
|
-
this.modal.id = 'action-bar-modal';
|
|
247
|
-
await document.body.appendChild(this.modal);
|
|
257
|
+
async showErrorModal(errorMsg, action) {
|
|
258
|
+
this.disableActionGroup = false;
|
|
248
259
|
|
|
249
|
-
//
|
|
260
|
+
// check if this.modal passed as prop
|
|
250
261
|
if (!this.modal) {
|
|
251
|
-
|
|
252
|
-
|
|
262
|
+
this.modal = document.querySelector('modal-manager');
|
|
263
|
+
|
|
264
|
+
// check the DOM if <modal-manager> already there
|
|
265
|
+
if (!this.modal) this.modal = document.createElement('modal-manager');
|
|
253
266
|
}
|
|
254
267
|
|
|
255
|
-
this.
|
|
256
|
-
this.
|
|
257
|
-
|
|
268
|
+
this.modal.id = 'action-bar-modal';
|
|
269
|
+
await document.body.appendChild(this.modal);
|
|
270
|
+
|
|
271
|
+
const modalConfig = new ModalConfig({
|
|
272
|
+
title: 'Lending error',
|
|
273
|
+
message: errorMsg,
|
|
274
|
+
headerColor: '#d9534f',
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
if (action === 'create_token') {
|
|
278
|
+
modalConfig.closeOnBackdropClick = false;
|
|
279
|
+
modalConfig.showCloseButton = false;
|
|
280
|
+
modalConfig.message = html` Uh oh, something went wrong trying to access
|
|
281
|
+
this book.<br />
|
|
282
|
+
Please <a href="${() => window.location.reload(true)}">refresh</a> to
|
|
283
|
+
try again or send us an email to
|
|
284
|
+
<a
|
|
285
|
+
href="mailto:info@archive.org?subject=Help: cannot access my borrowed book: ${this
|
|
286
|
+
.identifier}"
|
|
287
|
+
>info@archive.org</a
|
|
288
|
+
>`;
|
|
289
|
+
}
|
|
258
290
|
|
|
259
291
|
this.modal.showModal({
|
|
260
|
-
config:
|
|
292
|
+
config: modalConfig,
|
|
261
293
|
});
|
|
262
294
|
}
|
|
263
295
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { html, fixture, expect } from '@open-wc/testing';
|
|
2
2
|
import '../../src/components/collapsible-action-group.js';
|
|
3
|
-
import Sinon from 'sinon';
|
|
4
3
|
|
|
5
4
|
const container = ({
|
|
6
5
|
primaryActions = [
|
|
@@ -85,27 +84,3 @@ describe('<collapsible-action-group>', () => {
|
|
|
85
84
|
expect(eAnalytics.action).to.equal('Browse');
|
|
86
85
|
});
|
|
87
86
|
});
|
|
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
|
-
});
|
|
@@ -122,7 +122,7 @@ describe('Borrow status actions', () => {
|
|
|
122
122
|
el.addEventListener('lendingActionError', () => {
|
|
123
123
|
el.handleLendingActionError({
|
|
124
124
|
detail: {
|
|
125
|
-
|
|
125
|
+
action: 'browse_book',
|
|
126
126
|
data: { error: 'not available to borrow' },
|
|
127
127
|
},
|
|
128
128
|
});
|
|
@@ -151,7 +151,7 @@ describe('Borrow status actions', () => {
|
|
|
151
151
|
el.addEventListener('lendingActionError', () => {
|
|
152
152
|
el.handleLendingActionError({
|
|
153
153
|
detail: {
|
|
154
|
-
|
|
154
|
+
action: 'borrow_book',
|
|
155
155
|
data: { error: 'not available to borrow' },
|
|
156
156
|
},
|
|
157
157
|
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Helper function to fetch real-time lending status
|
|
3
|
-
*/
|
|
4
|
-
export default function getRealTimeLendingStatus(identifier) {
|
|
5
|
-
let url = `https://ia-petabox-neeraj.archive.org/services/book/lending-info.php?identifier=${identifier}`;
|
|
6
|
-
|
|
7
|
-
if (window.location.pathname === '/demo/') {
|
|
8
|
-
url = ''; // change URL to prevent error on localhost
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
fetch(url)
|
|
12
|
-
.then(response => {
|
|
13
|
-
// return { response_code: '400', data: 'error happened' };
|
|
14
|
-
return response.json();
|
|
15
|
-
})
|
|
16
|
-
.then(response => {
|
|
17
|
-
console.log(response);
|
|
18
|
-
if (response?.response_code === 200) {
|
|
19
|
-
const lendingInfo = response?.body?.data?.lendingInfo;
|
|
20
|
-
let newLendingInfo = lendingInfo;
|
|
21
|
-
const newLendingStatus = lendingInfo?.lendingStatus;
|
|
22
|
-
newLendingInfo = { ...newLendingInfo, ...newLendingStatus };
|
|
23
|
-
newLendingInfo.lendingStatus = '';
|
|
24
|
-
return newLendingInfo;
|
|
25
|
-
}
|
|
26
|
-
return null;
|
|
27
|
-
})
|
|
28
|
-
.catch(response => {
|
|
29
|
-
return response;
|
|
30
|
-
});
|
|
31
|
-
}
|