@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,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "0.0.10",
3
+ "version": "0.0.12-2",
4
4
  "description": "Bookreader actions for borrowable book",
5
5
  "author": "Internet Archive",
6
6
  "license": "AGPL-3.0-only",
@@ -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 = await this.localCache.get(storageKey);
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
- await this.localCache.set({
254
- key: storageKey,
255
- value: newCount,
256
- ttl: 7200, // 2 hours
257
- });
255
+ Cookies.setItem(storageKey, newCount, date, '/');
258
256
  } catch (error) {
259
- console.log(error);
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
- const expiry = date.toGMTString();
267
- let cookie = `loan-${this.identifier}=""`;
268
- cookie += `; expires=${expiry}`;
269
- cookie += '; path=/; domain=.archive.org;';
270
- document.cookie = cookie;
271
-
272
- cookie = `br-loan-${this.identifier}=""`;
273
- cookie += `; expires=${expiry}`;
274
- cookie += '; path=/; domain=.archive.org;';
275
- document.cookie = cookie;
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 = await this.localCache.get(
33
+ const existingCount = Cookies.getItem(
35
34
  `loan-count-${this.identifier}`
36
35
  );
37
36
  consecutiveLoanCounts = existingCount ?? 1;
38
37
  } catch (error) {
39
- console.log(error);
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
- this.errorCallback({ detail: { action, data } });
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();
@@ -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
- modalConfig.showCloseButton = false;
323
- modalConfig.message = html` Uh oh, something went wrong trying to access
324
- this book.<br />
325
- Please ${refreshButton} to try again or send us an email to
326
- <a
327
- href="mailto:info@archive.org?subject=Help: cannot access my borrowed book: ${this
328
- .identifier}"
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');