@internetarchive/ia-book-actions 0.0.10 → 0.0.12-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { LitElement } from 'lit-element';
|
|
2
|
-
import { LocalCache } from '@internetarchive/local-cache';
|
|
3
2
|
|
|
4
3
|
import { URLHelper } from '../../config/url-helper.js';
|
|
5
4
|
import ActionsHandlerService from './actions-handler-service.js';
|
|
5
|
+
import * as Cookies from '../doc-cookies.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* These are callback functions calling from actions-config.js file.
|
|
@@ -17,7 +17,6 @@ export default class ActionsHandler extends LitElement {
|
|
|
17
17
|
super();
|
|
18
18
|
this.identifier = identifier;
|
|
19
19
|
this.ajaxTimeout = 6000;
|
|
20
|
-
this.localCache = new LocalCache();
|
|
21
20
|
this.bindEvents();
|
|
22
21
|
}
|
|
23
22
|
|
|
@@ -242,36 +241,40 @@ export default class ActionsHandler extends LitElement {
|
|
|
242
241
|
try {
|
|
243
242
|
let newCount = 1;
|
|
244
243
|
const storageKey = `loan-count-${this.identifier}`;
|
|
245
|
-
const existingCount =
|
|
244
|
+
const existingCount = Cookies.getItem(storageKey);
|
|
246
245
|
|
|
247
246
|
// increase browse-count by 1 when you consecutive reading a book.
|
|
248
247
|
if (action === 'browseAgain' && existingCount !== undefined) {
|
|
249
|
-
newCount = existingCount ? existingCount + 1 : 1;
|
|
248
|
+
newCount = existingCount ? Number(existingCount) + 1 : 1;
|
|
250
249
|
}
|
|
251
250
|
|
|
251
|
+
const date = new Date();
|
|
252
|
+
date.setHours(date.getHours() + 2); // 2 hours
|
|
253
|
+
|
|
252
254
|
// set new value
|
|
253
|
-
|
|
254
|
-
key: storageKey,
|
|
255
|
-
value: newCount,
|
|
256
|
-
ttl: 7200, // 2 hours
|
|
257
|
-
});
|
|
255
|
+
Cookies.setItem(storageKey, newCount, date, '/');
|
|
258
256
|
} catch (error) {
|
|
259
|
-
|
|
257
|
+
this.sendEvent('Cookies-Error-Actions', error);
|
|
260
258
|
}
|
|
261
259
|
}
|
|
262
260
|
|
|
263
261
|
deleteLoanCookies() {
|
|
264
262
|
const date = new Date();
|
|
265
263
|
date.setTime(date.getTime() - 24 * 60 * 60 * 1000); // one day ago
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
264
|
+
|
|
265
|
+
Cookies.setItem(
|
|
266
|
+
`loan-${this.identifier}=""`,
|
|
267
|
+
'',
|
|
268
|
+
date,
|
|
269
|
+
'/',
|
|
270
|
+
'.archive.org'
|
|
271
|
+
);
|
|
272
|
+
Cookies.setItem(
|
|
273
|
+
`br-loan-${this.identifier}=""`,
|
|
274
|
+
'',
|
|
275
|
+
date,
|
|
276
|
+
'/',
|
|
277
|
+
'.archive.org'
|
|
278
|
+
);
|
|
276
279
|
}
|
|
277
280
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Helper module use to get, set and remove item from cookie
|
|
4
|
+
*
|
|
5
|
+
* See more:
|
|
6
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|
|
7
|
+
* https://developer.mozilla.org/User:fusionchess
|
|
8
|
+
* https://github.com/madmurphy/cookies.js
|
|
9
|
+
* This framework is released under the GNU Public License, version 3 or later.
|
|
10
|
+
* http://www.gnu.org/licenses/gpl-3.0-standalone.html
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get specific key's value stored in cookie
|
|
15
|
+
*
|
|
16
|
+
* @param {string} sKey
|
|
17
|
+
*
|
|
18
|
+
* @returns {string|null}
|
|
19
|
+
*/
|
|
20
|
+
export function getItem(sKey) {
|
|
21
|
+
if (!sKey) return null;
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
decodeURIComponent(
|
|
25
|
+
// eslint-disable-next-line no-useless-escape
|
|
26
|
+
document.cookie.replace(
|
|
27
|
+
new RegExp(
|
|
28
|
+
'(?:(?:^|.*;)\\s*' +
|
|
29
|
+
encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') +
|
|
30
|
+
'\\s*\\=\\s*([^;]*).*$)|^.*$'
|
|
31
|
+
),
|
|
32
|
+
'$1'
|
|
33
|
+
)
|
|
34
|
+
) || null
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Set specific key's value in cookie
|
|
40
|
+
*
|
|
41
|
+
* @param {string} sKey cookie name
|
|
42
|
+
* @param {string} sValue cookie value
|
|
43
|
+
* @param {string} [vEnd] expire|max-age
|
|
44
|
+
* @param {string} [sPath] path of current item
|
|
45
|
+
* @param {string} [sDomain] domain name
|
|
46
|
+
* @param {boolean} [bSecure]
|
|
47
|
+
*
|
|
48
|
+
* @returns {true}
|
|
49
|
+
*/
|
|
50
|
+
export function setItem(sKey, sValue, vEnd, sPath, sDomain, bSecure) {
|
|
51
|
+
document.cookie =
|
|
52
|
+
encodeURIComponent(sKey) +
|
|
53
|
+
'=' +
|
|
54
|
+
encodeURIComponent(sValue) +
|
|
55
|
+
(vEnd ? `; expires=${vEnd.toUTCString()}` : '') +
|
|
56
|
+
(sDomain ? `; domain=${sDomain}` : '') +
|
|
57
|
+
(sPath ? `; path=${sPath}` : '') +
|
|
58
|
+
(bSecure ? `; secure` : '');
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* BROKEN Remove specific key's value from cookie
|
|
65
|
+
* @fixme hasItem isn't even implemented! This will always error.
|
|
66
|
+
* @param {string} sKey cookie name
|
|
67
|
+
* @param {string} [sPath] path of current item
|
|
68
|
+
* @param {string} [sDomain]
|
|
69
|
+
*
|
|
70
|
+
* @returns {boolean}
|
|
71
|
+
*/
|
|
72
|
+
export function removeItem(sKey, sPath, sDomain) {
|
|
73
|
+
// eslint-disable-next-line
|
|
74
|
+
if (!hasItem(sKey)) return false;
|
|
75
|
+
|
|
76
|
+
document.cookie =
|
|
77
|
+
encodeURIComponent(sKey) +
|
|
78
|
+
`=; expires=Thu, 01 Jan 1970 00:00:00 GMT` +
|
|
79
|
+
(sDomain ? `; domain=${sDomain}` : '') +
|
|
80
|
+
(sPath ? `; path=${sPath}` : '');
|
|
81
|
+
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { LocalCache } from '@internetarchive/local-cache';
|
|
2
1
|
import ActionsHandlerService from './actions-handler/actions-handler-service.js';
|
|
2
|
+
import * as Cookies from './doc-cookies.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* This class is used to create loan token for borrowed books
|
|
@@ -15,7 +15,6 @@ export class LoanTokenPoller {
|
|
|
15
15
|
this.pollerDelay = pollerDelay; // value in ms (1000 ms = 1 sec)
|
|
16
16
|
|
|
17
17
|
this.loanTokenInterval = undefined;
|
|
18
|
-
this.localCache = new LocalCache();
|
|
19
18
|
this.enableBookAccess();
|
|
20
19
|
}
|
|
21
20
|
|
|
@@ -31,12 +30,12 @@ export class LoanTokenPoller {
|
|
|
31
30
|
// send consecutiveLoanCounts for browsed books only.
|
|
32
31
|
if (this.borrowType === 'browsed') {
|
|
33
32
|
try {
|
|
34
|
-
const existingCount =
|
|
33
|
+
const existingCount = Cookies.getItem(
|
|
35
34
|
`loan-count-${this.identifier}`
|
|
36
35
|
);
|
|
37
36
|
consecutiveLoanCounts = existingCount ?? 1;
|
|
38
37
|
} catch (error) {
|
|
39
|
-
|
|
38
|
+
this.sendEvent('Cookies-Error-Token', error);
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
|
|
@@ -77,7 +76,12 @@ export class LoanTokenPoller {
|
|
|
77
76
|
action,
|
|
78
77
|
error: data => {
|
|
79
78
|
this.disconnectedInterval(); // stop token fetch api
|
|
80
|
-
|
|
79
|
+
|
|
80
|
+
if (isInitial) {
|
|
81
|
+
this.errorCallback({ detail: { action, data } });
|
|
82
|
+
} else {
|
|
83
|
+
this.errorCallback({ detail: { action, data, isExpired: true } });
|
|
84
|
+
}
|
|
81
85
|
},
|
|
82
86
|
success: () => {
|
|
83
87
|
if (isInitial) this.successCallback();
|
package/src/ia-book-actions.js
CHANGED
|
@@ -162,6 +162,10 @@ export default class IABookActions extends LitElement {
|
|
|
162
162
|
this.startBrowseTimer();
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
if (this.lendingStatus.browsingExpired) {
|
|
166
|
+
this.tokenPoller.disconnectedInterval();
|
|
167
|
+
}
|
|
168
|
+
|
|
165
169
|
// early return if not borrowed or no action-bar
|
|
166
170
|
if (!this.borrowType || this.barType === 'title') {
|
|
167
171
|
this.lendingBarPostInit();
|
|
@@ -261,6 +265,7 @@ export default class IABookActions extends LitElement {
|
|
|
261
265
|
* @param {Object} event - The employee who is responsible for the project
|
|
262
266
|
* @param {string} event.detail.action - action when error occurred like 'browseBook', 'borrowBook'
|
|
263
267
|
* @param {string} event.detail.data.error - error message
|
|
268
|
+
* @param {string} event.detail.data.isExpired - triggered when loan is expired
|
|
264
269
|
*/
|
|
265
270
|
handleLendingActionError(event) {
|
|
266
271
|
// toggle activity loader
|
|
@@ -268,8 +273,9 @@ export default class IABookActions extends LitElement {
|
|
|
268
273
|
|
|
269
274
|
const action = event?.detail?.action;
|
|
270
275
|
const errorMsg = event?.detail?.data?.error;
|
|
276
|
+
const loanExpired = event?.detail?.data?.isExpired;
|
|
271
277
|
|
|
272
|
-
if (errorMsg) this.showErrorModal(errorMsg, action);
|
|
278
|
+
if (errorMsg) this.showErrorModal(errorMsg, action, loanExpired);
|
|
273
279
|
|
|
274
280
|
// update action bar state if book is not available to browse or borrow.
|
|
275
281
|
if (errorMsg && errorMsg.match(/not available to borrow/gm)) {
|
|
@@ -290,7 +296,7 @@ export default class IABookActions extends LitElement {
|
|
|
290
296
|
}
|
|
291
297
|
|
|
292
298
|
/* show error message if something went wrong */
|
|
293
|
-
async showErrorModal(errorMsg, action) {
|
|
299
|
+
async showErrorModal(errorMsg, action, loanExpired) {
|
|
294
300
|
this.disableActionGroup = false;
|
|
295
301
|
|
|
296
302
|
// check if this.modal passed as prop
|
|
@@ -311,23 +317,14 @@ export default class IABookActions extends LitElement {
|
|
|
311
317
|
});
|
|
312
318
|
|
|
313
319
|
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
|
-
|
|
321
320
|
modalConfig.closeOnBackdropClick = false;
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
>info@archive.org</a
|
|
330
|
-
>`;
|
|
321
|
+
if (loanExpired) {
|
|
322
|
+
modalConfig.showCloseButton = true;
|
|
323
|
+
modalConfig.message = this.loanExpiredMessage;
|
|
324
|
+
} else {
|
|
325
|
+
modalConfig.showCloseButton = false;
|
|
326
|
+
modalConfig.message = this.loanErrorMessage;
|
|
327
|
+
}
|
|
331
328
|
}
|
|
332
329
|
|
|
333
330
|
this.modal.showModal({
|
|
@@ -335,6 +332,29 @@ export default class IABookActions extends LitElement {
|
|
|
335
332
|
});
|
|
336
333
|
}
|
|
337
334
|
|
|
335
|
+
/* eslint-disable class-methods-use-this */
|
|
336
|
+
get loanExpiredMessage() {
|
|
337
|
+
return html`Your current loan is expired, please close this model and click
|
|
338
|
+
on <strong>Borrow Again</strong> button to continue reading this book`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
get loanErrorMessage() {
|
|
342
|
+
const refreshButton = html`<button
|
|
343
|
+
style="background:none;font-size:inherit;border:0;padding:0;color:#0000ee;cursor:pointer;text-decoration:underline"
|
|
344
|
+
@click=${() => window.location.reload(true)}
|
|
345
|
+
>
|
|
346
|
+
refresh
|
|
347
|
+
</button>`;
|
|
348
|
+
|
|
349
|
+
return html`Uh oh, something went wrong trying to access this book.<br />
|
|
350
|
+
Please ${refreshButton} to try again or send us an email to
|
|
351
|
+
<a
|
|
352
|
+
href="mailto:info@archive.org?subject=Help: cannot access my borrowed book: ${this
|
|
353
|
+
.identifier}"
|
|
354
|
+
>info@archive.org</a
|
|
355
|
+
>`;
|
|
356
|
+
}
|
|
357
|
+
|
|
338
358
|
get iconClass() {
|
|
339
359
|
return this.width <= mobileContainerWidth ? 'mobile' : 'desktop';
|
|
340
360
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { expect } from '@open-wc/testing';
|
|
2
2
|
import Sinon from 'sinon';
|
|
3
3
|
|
|
4
|
-
import { LocalCache } from '@internetarchive/local-cache';
|
|
4
|
+
// import { LocalCache } from '@internetarchive/local-cache';
|
|
5
5
|
import { LoanTokenPoller } from '../../../src/core/services/loan-token-poller.js';
|
|
6
6
|
|
|
7
7
|
describe('Get Loan Token', () => {
|
|
8
8
|
it('get loan token for browsed books', async () => {
|
|
9
|
-
const localCacheStub = new LocalCache();
|
|
10
|
-
const localCacheGetSpy = Sinon.spy(localCacheStub, 'get');
|
|
9
|
+
// const localCacheStub = new LocalCache();
|
|
10
|
+
// const localCacheGetSpy = Sinon.spy(localCacheStub, 'get');
|
|
11
11
|
|
|
12
12
|
const tokenPoller = new LoanTokenPoller(
|
|
13
13
|
'identifier1',
|
|
@@ -24,14 +24,14 @@ describe('Get Loan Token', () => {
|
|
|
24
24
|
successCallbackSpy();
|
|
25
25
|
expect(successCallbackSpy.callCount).to.equal(1);
|
|
26
26
|
|
|
27
|
-
localCacheGetSpy();
|
|
28
|
-
expect(localCacheGetSpy.callCount).to.equal(1);
|
|
27
|
+
// localCacheGetSpy();
|
|
28
|
+
// expect(localCacheGetSpy.callCount).to.equal(1);
|
|
29
29
|
|
|
30
|
-
expect(tokenPoller.localCache.namespace).to.equal('LocalCache');
|
|
31
|
-
expect(tokenPoller.localCache.get).to.be.a('function');
|
|
30
|
+
// expect(tokenPoller.localCache.namespace).to.equal('LocalCache');
|
|
31
|
+
// expect(tokenPoller.localCache.get).to.be.a('function');
|
|
32
32
|
|
|
33
|
-
tokenPoller.disconnectedInterval(); // clear token poller interval
|
|
34
|
-
expect(tokenPoller.loanTokenInterval).to.equal(undefined);
|
|
33
|
+
// tokenPoller.disconnectedInterval(); // clear token poller interval
|
|
34
|
+
// expect(tokenPoller.loanTokenInterval).to.equal(undefined);
|
|
35
35
|
|
|
36
36
|
tokenPoller.handleLoanTokenPoller(true);
|
|
37
37
|
expect(tokenPoller.errorCallback).to.be.a('function');
|