@internetarchive/ia-book-actions 0.0.7-9 → 0.0.8

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 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.7-9",
3
+ "version": "0.0.8",
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.1.1",
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",
@@ -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 = 7000;
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 = `consecutive-loan-count`;
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 extends LitElement {
12
- constructor() {
13
- super();
14
- this.identifier = '';
15
- this.loanTokenPollingDelay = window.location.pathname === '/demo/' ? 2000 : 120000; // 120000 ms = 2 min
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
- disconnectedCallback() {
22
+ disconnectedInterval() {
23
+ clearInterval(this.loanTokenInterval);
21
24
  this.loanTokenInterval = undefined;
22
25
  }
23
26
 
24
- async enableBookAccess(identifier, borrowType) {
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
- 'consecutive-loan-count'
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.loanTokenPollingDelay);
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
- console.log(consecutiveLoanCounts)
55
+
54
56
  this.sendEvent(category, action);
55
57
  } else {
56
58
  // if book is not browsed, just clear token polling interval
57
- clearInterval(this.loanTokenInterval);
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
- console.log('error', data);
79
- this.handleLendingActionError({detail: { action, data }})
80
- // this.dispatchActionError(action, data);
81
- clearInterval(this.loanTokenInterval); // stop token fetch api
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
  }
@@ -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 LoanTokenPoller {
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: { type: Function },
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,51 @@ export default class IABookActions extends LoanTokenPoller {
157
162
  this.startBrowseTimer();
158
163
  }
159
164
 
160
- // enable access of borrowed/browsed books
161
- if (this.borrowType) {
162
- await this.enableBookAccess(this.identifier, this.borrowType);
163
- }
164
-
165
165
  /**
166
- * this callback function use to:-
167
- * - disptach lenfingFlow::PostInit event
168
- * - initialize bookreader using br.init()
166
+ * enable access of borrowed/browsed books
167
+ *
168
+ * LoanTokenPoller is a class that polls the loan token
169
+ * it takes 5 params
170
+ * 1. this.identifier
171
+ * 2. this.borrowType
172
+ * 3. successCallback - it used to
173
+ * - disptach lendingFlow::PostInit event
174
+ * - initialize bookreader using br.init()
175
+ * 4. errorCallback
176
+ * 5. tokenPollerDelay
169
177
  */
170
- console.log(this.lendingBarPostInit);
171
- this.lendingBarPostInit;
178
+ if (this.barType === 'action') {
179
+ if (this.tokenPoller) {
180
+ this.tokenPoller.disconnectedInterval();
181
+ }
182
+
183
+ const successCallback = () => {
184
+ this.lendingBarPostInit();
185
+ };
186
+ const errorCallback = eventObj => {
187
+ this.handleLendingActionError(eventObj);
188
+ };
189
+
190
+ this.tokenPoller = new LoanTokenPoller(
191
+ this.identifier,
192
+ this.borrowType,
193
+ successCallback,
194
+ errorCallback,
195
+ this.tokenDelay // 1000 ms = 1 sec
196
+ );
197
+ }
172
198
  }
173
199
 
174
200
  render() {
175
201
  if (this.barType === 'title') {
176
- return html`<section class="lending-wrapper">${this.bookTitleBar}</section>`;
202
+ return html`<section class="lending-wrapper">
203
+ ${this.bookTitleBar}
204
+ </section>`;
177
205
  }
178
206
 
179
- return html`<section class="lending-wrapper">${this.bookActionBar}</section>`;
207
+ return html`<section class="lending-wrapper">
208
+ ${this.bookActionBar}
209
+ </section>`;
180
210
  }
181
211
 
182
212
  get bookTitleBar() {
@@ -273,12 +303,18 @@ export default class IABookActions extends LoanTokenPoller {
273
303
  });
274
304
 
275
305
  if (action === 'create_token') {
306
+ const refreshButton = html`<button
307
+ style="background:none;font-size:inherit;border:0;padding:0;color:#0000ee;cursor:pointer;text-decoration:underline"
308
+ @click=${() => window.location.reload(true)}
309
+ >
310
+ refresh
311
+ </button>`;
312
+
276
313
  modalConfig.closeOnBackdropClick = false;
277
314
  modalConfig.showCloseButton = false;
278
315
  modalConfig.message = html` Uh oh, something went wrong trying to access
279
316
  this book.<br />
280
- Please <a href="${() => window.location.reload(true)}">refresh</a> to
281
- try again or send us an email to
317
+ Please ${refreshButton} to try again or send us an email to
282
318
  <a
283
319
  href="mailto:info@archive.org?subject=Help: cannot access my borrowed book: ${this
284
320
  .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
+ });