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

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-1",
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,25 @@ 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);
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">${this.bookTitleBar}</section>`;
176
+ return html`<section class="lending-wrapper">
177
+ ${this.bookTitleBar}
178
+ </section>`;
177
179
  }
178
180
 
179
- return html`<section class="lending-wrapper">${this.bookActionBar}</section>`;
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 <a href="${() => window.location.reload(true)}">refresh</a> to
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
+ });