@internetarchive/ia-book-actions 0.0.7-9 → 0.0.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 +3 -4
- package/package.json +2 -2
- package/src/components/info-icon.js +1 -1
- package/src/core/services/actions-handler/actions-handler.js +2 -3
- package/src/core/services/loan-token-poller.js +27 -43
- package/src/ia-book-actions.js +61 -17
- package/test/core/services/loan-token-poller.test.js +40 -0
package/demo/index.html
CHANGED
|
@@ -106,20 +106,19 @@
|
|
|
106
106
|
|
|
107
107
|
let lendingBarPostInit = function lendingBarPostInit() {
|
|
108
108
|
setTimeout(function() {
|
|
109
|
-
console.log('executed');
|
|
110
|
-
// emitLendingActionBarInitEvent();
|
|
111
|
-
// brInit();
|
|
109
|
+
console.log('executed', 'br.init()');
|
|
112
110
|
}, 100);
|
|
113
111
|
}
|
|
112
|
+
|
|
114
113
|
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
115
114
|
iaBookActions.userid = userid;
|
|
116
115
|
iaBookActions.identifier = identifier;
|
|
117
116
|
iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
|
|
118
117
|
iaBookActions.lendingStatus = canBrowseAndBorrow;
|
|
119
118
|
iaBookActions.bwbPurchaseUrl = '';
|
|
120
|
-
iaBookActions.barType = '';
|
|
121
119
|
iaBookActions.modalConfig = modalConfig;
|
|
122
120
|
iaBookActions.lendingBarPostInit = lendingBarPostInit;
|
|
121
|
+
iaBookActions.tokenDelay = 2000; // 2 seconds
|
|
123
122
|
|
|
124
123
|
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
125
124
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/ia-book-actions",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Bookreader actions for borrowable book",
|
|
5
5
|
"author": "Internet Archive",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -22,7 +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.
|
|
25
|
+
"@internetarchive/local-cache": "^0.2.0",
|
|
26
26
|
"@internetarchive/modal-manager": "^0.1.0",
|
|
27
27
|
"@internetarchive/shared-resize-observer": "^0.0.1",
|
|
28
28
|
"lit-element": "^2.4.0",
|
|
@@ -13,7 +13,7 @@ export class InfoIcon extends LitElement {
|
|
|
13
13
|
super();
|
|
14
14
|
this.iconClass = '';
|
|
15
15
|
this.helpURL =
|
|
16
|
-
'https://help.archive.org/
|
|
16
|
+
'https://help.archive.org/help/borrowing-from-the-lending-library';
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
render() {
|
|
@@ -16,7 +16,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
16
16
|
constructor(identifier) {
|
|
17
17
|
super();
|
|
18
18
|
this.identifier = identifier;
|
|
19
|
-
this.ajaxTimeout =
|
|
19
|
+
this.ajaxTimeout = 6000;
|
|
20
20
|
this.localCache = new LocalCache();
|
|
21
21
|
this.bindEvents();
|
|
22
22
|
}
|
|
@@ -178,7 +178,6 @@ export default class ActionsHandler extends LitElement {
|
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
|
|
182
181
|
/**
|
|
183
182
|
* Dispatches event when an error occured on action
|
|
184
183
|
* Notes:- toggle <collapsible-action-group> visibility (enable/disable).
|
|
@@ -242,7 +241,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
242
241
|
async setConsecutiveLoanCounts(action = '') {
|
|
243
242
|
try {
|
|
244
243
|
let newCount = 1;
|
|
245
|
-
const storageKey = `
|
|
244
|
+
const storageKey = `loan-count-${this.identifier}`;
|
|
246
245
|
const existingCount = await this.localCache.get(storageKey);
|
|
247
246
|
|
|
248
247
|
// increase browse-count by 1 when you consecutive reading a book.
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { LitElement } from 'lit-element';
|
|
2
1
|
import { LocalCache } from '@internetarchive/local-cache';
|
|
3
|
-
|
|
4
2
|
import ActionsHandlerService from './actions-handler/actions-handler-service.js';
|
|
5
3
|
|
|
6
4
|
/**
|
|
@@ -8,29 +6,33 @@ import ActionsHandlerService from './actions-handler/actions-handler-service.js'
|
|
|
8
6
|
*
|
|
9
7
|
* ActionsHandlerService is a function being used to execute
|
|
10
8
|
*/
|
|
11
|
-
export class LoanTokenPoller
|
|
12
|
-
constructor() {
|
|
13
|
-
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
9
|
+
export class LoanTokenPoller {
|
|
10
|
+
constructor(id, borrowType, successCallback, errorCallback, pollerDelay) {
|
|
11
|
+
this.identifier = id;
|
|
12
|
+
this.borrowType = borrowType;
|
|
13
|
+
this.successCallback = successCallback; // callback function to be called after loan token is created
|
|
14
|
+
this.errorCallback = errorCallback; // callback function to be called after loan token is created
|
|
15
|
+
this.pollerDelay = pollerDelay; // value in ms (1000 ms = 1 sec)
|
|
16
|
+
|
|
16
17
|
this.loanTokenInterval = undefined;
|
|
17
18
|
this.localCache = new LocalCache();
|
|
19
|
+
this.enableBookAccess();
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
disconnectedInterval() {
|
|
23
|
+
clearInterval(this.loanTokenInterval);
|
|
21
24
|
this.loanTokenInterval = undefined;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
async enableBookAccess(
|
|
25
|
-
this.identifier = identifier
|
|
27
|
+
async enableBookAccess() {
|
|
26
28
|
let consecutiveLoanCounts = 1;
|
|
27
29
|
|
|
28
|
-
if (borrowType) {
|
|
30
|
+
if (this.borrowType) {
|
|
29
31
|
// send consecutiveLoanCounts for browsed books only.
|
|
30
|
-
if (borrowType === 'browsed') {
|
|
32
|
+
if (this.borrowType === 'browsed') {
|
|
31
33
|
try {
|
|
32
34
|
const existingCount = await this.localCache.get(
|
|
33
|
-
|
|
35
|
+
`loan-count-${this.identifier}`
|
|
34
36
|
);
|
|
35
37
|
consecutiveLoanCounts = existingCount ?? 1;
|
|
36
38
|
} catch (error) {
|
|
@@ -39,22 +41,22 @@ export class LoanTokenPoller extends LitElement {
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
// Do an initial token, then set an interval
|
|
42
|
-
this.handleLoanTokenPoller();
|
|
44
|
+
this.handleLoanTokenPoller(true);
|
|
43
45
|
|
|
44
46
|
this.loanTokenInterval = setInterval(() => {
|
|
45
47
|
this.handleLoanTokenPoller();
|
|
46
|
-
}, this.
|
|
48
|
+
}, this.pollerDelay);
|
|
47
49
|
|
|
48
50
|
// event category and action for browsing book access
|
|
49
|
-
const category = `${borrowType}BookAccess`;
|
|
51
|
+
const category = `${this.borrowType}BookAccess`;
|
|
50
52
|
const action = `${
|
|
51
|
-
borrowType === 'browsed' ? 'BrowseCounts-' : 'Counts-'
|
|
53
|
+
this.borrowType === 'browsed' ? 'BrowseCounts-' : 'Counts-'
|
|
52
54
|
}${consecutiveLoanCounts}`;
|
|
53
|
-
|
|
55
|
+
|
|
54
56
|
this.sendEvent(category, action);
|
|
55
57
|
} else {
|
|
56
58
|
// if book is not browsed, just clear token polling interval
|
|
57
|
-
|
|
59
|
+
this.disconnectedInterval(); // stop token fetch api
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -68,36 +70,18 @@ export class LoanTokenPoller extends LitElement {
|
|
|
68
70
|
);
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
async handleLoanTokenPoller() {
|
|
73
|
+
async handleLoanTokenPoller(isInitial = false) {
|
|
72
74
|
const action = 'create_token';
|
|
73
|
-
// await new Promise(r => setTimeout(r, 3000));
|
|
74
75
|
ActionsHandlerService({
|
|
75
76
|
identifier: this.identifier,
|
|
76
77
|
action,
|
|
77
78
|
error: data => {
|
|
78
|
-
|
|
79
|
-
this.
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
this.disconnectedInterval(); // stop token fetch api
|
|
80
|
+
this.errorCallback({ detail: { action, data } });
|
|
81
|
+
},
|
|
82
|
+
success: () => {
|
|
83
|
+
if (isInitial) this.successCallback();
|
|
82
84
|
},
|
|
83
85
|
});
|
|
84
86
|
}
|
|
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
87
|
}
|
package/src/ia-book-actions.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable camelcase */
|
|
2
|
-
import { html, css } from 'lit-element';
|
|
2
|
+
import { html, css, LitElement } from 'lit-element';
|
|
3
3
|
|
|
4
4
|
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
|
5
5
|
import { ModalConfig } from '@internetarchive/modal-manager';
|
|
@@ -13,7 +13,7 @@ import GetLendingActions from './core/services/get-lending-actions.js';
|
|
|
13
13
|
import { mobileContainerWidth } from './core/config/constants.js';
|
|
14
14
|
import { LoanTokenPoller } from './core/services/loan-token-poller.js';
|
|
15
15
|
|
|
16
|
-
export default class IABookActions extends
|
|
16
|
+
export default class IABookActions extends LitElement {
|
|
17
17
|
static get properties() {
|
|
18
18
|
return {
|
|
19
19
|
userid: { type: String },
|
|
@@ -22,11 +22,15 @@ export default class IABookActions extends LoanTokenPoller {
|
|
|
22
22
|
lendingStatus: { type: Object },
|
|
23
23
|
width: { type: Number },
|
|
24
24
|
bwbPurchaseUrl: { type: String },
|
|
25
|
-
lendingBarPostInit: {
|
|
25
|
+
lendingBarPostInit: {
|
|
26
|
+
type: Function,
|
|
27
|
+
attribute: false,
|
|
28
|
+
},
|
|
26
29
|
barType: { type: String },
|
|
27
30
|
sharedObserver: { attribute: false },
|
|
28
31
|
disableActionGroup: { type: Boolean },
|
|
29
32
|
modal: { Object },
|
|
33
|
+
tokenDelay: { type: Number },
|
|
30
34
|
};
|
|
31
35
|
}
|
|
32
36
|
|
|
@@ -43,6 +47,7 @@ export default class IABookActions extends LoanTokenPoller {
|
|
|
43
47
|
this.sharedObserver = undefined;
|
|
44
48
|
this.disableActionGroup = false;
|
|
45
49
|
this.modal = undefined;
|
|
50
|
+
this.tokenDelay = 120000; // 2 minutes
|
|
46
51
|
|
|
47
52
|
// private props
|
|
48
53
|
this.primaryActions = [];
|
|
@@ -157,26 +162,25 @@ export default class IABookActions extends LoanTokenPoller {
|
|
|
157
162
|
this.startBrowseTimer();
|
|
158
163
|
}
|
|
159
164
|
|
|
160
|
-
//
|
|
161
|
-
if (this.borrowType) {
|
|
162
|
-
|
|
165
|
+
// early return if not borrowed or no action-bar
|
|
166
|
+
if (!this.borrowType || this.barType === 'title') {
|
|
167
|
+
this.lendingBarPostInit();
|
|
168
|
+
return;
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
|
|
166
|
-
* this callback function use to:-
|
|
167
|
-
* - disptach lenfingFlow::PostInit event
|
|
168
|
-
* - initialize bookreader using br.init()
|
|
169
|
-
*/
|
|
170
|
-
console.log(this.lendingBarPostInit);
|
|
171
|
-
this.lendingBarPostInit;
|
|
171
|
+
this.startLoanTokenPoller();
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
render() {
|
|
175
175
|
if (this.barType === 'title') {
|
|
176
|
-
return html`<section class="lending-wrapper"
|
|
176
|
+
return html`<section class="lending-wrapper">
|
|
177
|
+
${this.bookTitleBar}
|
|
178
|
+
</section>`;
|
|
177
179
|
}
|
|
178
180
|
|
|
179
|
-
return html`<section class="lending-wrapper"
|
|
181
|
+
return html`<section class="lending-wrapper">
|
|
182
|
+
${this.bookActionBar}
|
|
183
|
+
</section>`;
|
|
180
184
|
}
|
|
181
185
|
|
|
182
186
|
get bookTitleBar() {
|
|
@@ -206,6 +210,40 @@ export default class IABookActions extends LoanTokenPoller {
|
|
|
206
210
|
`;
|
|
207
211
|
}
|
|
208
212
|
|
|
213
|
+
/**
|
|
214
|
+
* enable access of borrowed/browsed books
|
|
215
|
+
*/
|
|
216
|
+
startLoanTokenPoller() {
|
|
217
|
+
if (this.tokenPoller) {
|
|
218
|
+
this.tokenPoller.disconnectedInterval();
|
|
219
|
+
}
|
|
220
|
+
const successCallback = () => {
|
|
221
|
+
this.lendingBarPostInit();
|
|
222
|
+
};
|
|
223
|
+
const errorCallback = eventObj => {
|
|
224
|
+
this.handleLendingActionError(eventObj);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* LoanTokenPoller is a class that polls the loan token
|
|
229
|
+
* it takes 5 params
|
|
230
|
+
* 1. this.identifier
|
|
231
|
+
* 2. this.borrowType
|
|
232
|
+
* 3. successCallback - it used to
|
|
233
|
+
* - disptach lendingFlow::PostInit event
|
|
234
|
+
* - initialize bookreader using br.init()
|
|
235
|
+
* 4. errorCallback
|
|
236
|
+
* 5. tokenPollerDelay
|
|
237
|
+
*/
|
|
238
|
+
this.tokenPoller = new LoanTokenPoller(
|
|
239
|
+
this.identifier,
|
|
240
|
+
this.borrowType,
|
|
241
|
+
successCallback,
|
|
242
|
+
errorCallback,
|
|
243
|
+
this.tokenDelay // 1000 ms = 1 sec
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
209
247
|
/*
|
|
210
248
|
* custom event handler to toggle action group visibility
|
|
211
249
|
*
|
|
@@ -273,12 +311,18 @@ export default class IABookActions extends LoanTokenPoller {
|
|
|
273
311
|
});
|
|
274
312
|
|
|
275
313
|
if (action === 'create_token') {
|
|
314
|
+
const refreshButton = html`<button
|
|
315
|
+
style="background:none;font-size:inherit;border:0;padding:0;color:#0000ee;cursor:pointer;text-decoration:underline"
|
|
316
|
+
@click=${() => window.location.reload(true)}
|
|
317
|
+
>
|
|
318
|
+
refresh
|
|
319
|
+
</button>`;
|
|
320
|
+
|
|
276
321
|
modalConfig.closeOnBackdropClick = false;
|
|
277
322
|
modalConfig.showCloseButton = false;
|
|
278
323
|
modalConfig.message = html` Uh oh, something went wrong trying to access
|
|
279
324
|
this book.<br />
|
|
280
|
-
Please
|
|
281
|
-
try again or send us an email to
|
|
325
|
+
Please ${refreshButton} to try again or send us an email to
|
|
282
326
|
<a
|
|
283
327
|
href="mailto:info@archive.org?subject=Help: cannot access my borrowed book: ${this
|
|
284
328
|
.identifier}"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
import Sinon from 'sinon';
|
|
3
|
+
|
|
4
|
+
import { LocalCache } from '@internetarchive/local-cache';
|
|
5
|
+
import { LoanTokenPoller } from '../../../src/core/services/loan-token-poller.js';
|
|
6
|
+
|
|
7
|
+
describe('Get Loan Token', () => {
|
|
8
|
+
it('get loan token for browsed books', async () => {
|
|
9
|
+
const localCacheStub = new LocalCache();
|
|
10
|
+
const localCacheGetSpy = Sinon.spy(localCacheStub, 'get');
|
|
11
|
+
|
|
12
|
+
const tokenPoller = new LoanTokenPoller(
|
|
13
|
+
'identifier1',
|
|
14
|
+
'browsed',
|
|
15
|
+
() => {
|
|
16
|
+
console.log('success callback is executed!');
|
|
17
|
+
},
|
|
18
|
+
() => {
|
|
19
|
+
console.log('error callback is executed!');
|
|
20
|
+
},
|
|
21
|
+
2000 // 2 minutes'
|
|
22
|
+
);
|
|
23
|
+
const successCallbackSpy = Sinon.stub(tokenPoller, 'successCallback');
|
|
24
|
+
successCallbackSpy();
|
|
25
|
+
expect(successCallbackSpy.callCount).to.equal(1);
|
|
26
|
+
|
|
27
|
+
localCacheGetSpy();
|
|
28
|
+
expect(localCacheGetSpy.callCount).to.equal(1);
|
|
29
|
+
|
|
30
|
+
expect(tokenPoller.localCache.namespace).to.equal('LocalCache');
|
|
31
|
+
expect(tokenPoller.localCache.get).to.be.a('function');
|
|
32
|
+
|
|
33
|
+
tokenPoller.disconnectedInterval(); // clear token poller interval
|
|
34
|
+
expect(tokenPoller.loanTokenInterval).to.equal(undefined);
|
|
35
|
+
|
|
36
|
+
tokenPoller.handleLoanTokenPoller(true);
|
|
37
|
+
expect(tokenPoller.errorCallback).to.be.a('function');
|
|
38
|
+
expect(tokenPoller.successCallback).have;
|
|
39
|
+
});
|
|
40
|
+
});
|