@internetarchive/ia-book-actions 0.0.29-alpha4 → 0.0.29-alpha40

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.
@@ -3,6 +3,7 @@ import { html, css, LitElement, nothing } from 'lit';
3
3
 
4
4
  import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
5
5
  import { ModalConfig } from '@internetarchive/modal-manager';
6
+ import { ToastConfig } from '@internetarchive/toast-manager';
6
7
  import { LocalCache } from '@internetarchive/local-cache';
7
8
 
8
9
  import './components/collapsible-action-group.js';
@@ -10,12 +11,12 @@ import './components/book-title-bar.js';
10
11
  import './components/text-group.js';
11
12
  import './components/info-icon.js';
12
13
  import './components/timer-countdown.js';
13
- import './components/toast-message.js';
14
14
 
15
15
  import { GetLendingActions } from './core/services/get-lending-actions.js';
16
16
  import { mobileContainerWidth } from './core/config/constants.js';
17
+ import { sentryLogs } from './core/config/sentry-events.js';
17
18
  import { LoanTokenPoller } from './core/services/loan-token-poller.js';
18
- import { OneHourAutoRenew } from './core/services/one-hour-auto-renew.js';
19
+ import { LoanRenewHelper } from './core/services/loan-renew-helper.js';
19
20
 
20
21
  export const events = {
21
22
  browseExpired: 'IABookReader:BrowsingHasExpired',
@@ -36,17 +37,13 @@ export default class IABookActions extends LitElement {
36
37
  attribute: false,
37
38
  },
38
39
  barType: { type: String },
39
- autoRenew: { type: Boolean },
40
40
  sharedObserver: { attribute: false },
41
41
  disableActionGroup: { type: Boolean },
42
42
  modal: { Object },
43
43
  tokenDelay: { type: Number },
44
- toastTexts: { type: String },
45
- remainingTime: { type: Number },
46
- resetTimerCountdown: { type: Boolean },
47
44
  localCache: { type: Object },
48
- autoRenewConfig: { type: Object },
49
- browseAgainNow: { type: Boolean },
45
+ loanRenewTimeConfig: { type: Object },
46
+ loanRenewResult: { type: Object },
50
47
  };
51
48
  }
52
49
 
@@ -61,16 +58,10 @@ export default class IABookActions extends LitElement {
61
58
  this.bwbPurchaseUrl = '';
62
59
  this.lendingBarPostInit = () => {};
63
60
  this.barType = 'action'; // 'title'|'action'
64
- this.autoRenew = false;
65
61
  this.sharedObserver = undefined;
66
62
  this.disableActionGroup = false;
67
63
  this.modal = undefined;
68
- this.tokenDelay = 120000; // 2 minutes
69
- this.localCache = new LocalCache({
70
- namespace: '1HourLoanStorage'
71
- }),
72
- this.autoRenewConfig = {},
73
- this.autoRenewObj = undefined;
64
+ this.tokenDelay = 120; // in seconds
74
65
 
75
66
  // private props
76
67
  this.primaryActions = [];
@@ -80,21 +71,52 @@ export default class IABookActions extends LitElement {
80
71
  this.lendingOptions = {};
81
72
  this.borrowType = ''; // (browsed|borrowed)
82
73
  this.consecutiveLoanCounts = 1; // consecutive loan count
83
- this.browseAgainNow = false;
84
- this.browserTimer = undefined;
85
- this.hideToast = true;
74
+ this.suppressToast = false;
75
+ this.browseTimer = undefined;
76
+
77
+ /**
78
+ * contains one hour auto-loan-renew time configuration
79
+ *
80
+ * @type {object} loanRenewTimeConfig
81
+ * @property {number} loanTotalTime - number of seconds a loan should last
82
+ * @property {number} loanRenewAtLast - check for loan renew at last
83
+ * @property {number} pageChangedInLast - consider loan renew eligible if viewed new page
84
+ * @property {boolean} isDevBox - testing flag
85
+ */
86
+ this.loanRenewTimeConfig = {};
87
+
88
+ /**
89
+ * contains one hour auto-loan-renew response
90
+ *
91
+ * @type {object} loanRenewResult
92
+ * @property {string} texts - texts messages need to show in toast message
93
+ * @property {boolean} renewNow - key to determine if need to renew now
94
+ * @property {number} secondsLeft - seconds left in active loan
95
+ */
96
+ this.loanRenewResult = { texts: '', renewNow: false, secondsLeft: 0 };
86
97
 
87
- this.bindAutoRenewEvent();
88
- this.resetTimerCountdown = false;
98
+ /**
99
+ * need showdowRoot opened for resetTimerCountState
100
+ * @see IABookActions::resetTimerCountState
101
+ */
102
+ this._shadowRoot = this.attachShadow({ mode: 'open' });
89
103
  }
90
104
 
91
105
  disconnectedCallback() {
92
106
  this.tokenPoller?.disconnectedInterval();
93
- window?.Sentry?.captureMessage('disconnectedCallback');
107
+ window?.Sentry?.captureMessage(sentryLogs.disconnectedCallback);
94
108
  this.disconnectResizeObserver();
95
109
  }
96
110
 
97
111
  firstUpdated() {
112
+ // bind auto loan renew events
113
+ this.bindLoanRenewEvents();
114
+
115
+ // localCache used for auto-loan-renew
116
+ this.localCache = new LocalCache({
117
+ namespace: 'loanRenew',
118
+ });
119
+
98
120
  if (!this.sharedObserver) {
99
121
  this.sharedObserver = new SharedResizeObserver();
100
122
  this.setupResizeObserver();
@@ -102,86 +124,17 @@ export default class IABookActions extends LitElement {
102
124
  }
103
125
 
104
126
  updated(changed) {
105
- console.log(changed)
106
127
  if (changed.has('lendingStatus') || changed.has('bwbPurchaseUrl')) {
107
128
  this.setupLendingToolbarActions();
108
129
  this.update();
109
130
  }
110
131
 
111
- if (changed.has('autoRenew')) {
112
- this.resetTimerCountdown = true;
113
- }
114
132
  if (changed.has('sharedObserver')) {
115
133
  this.disconnectResizeObserver();
116
134
  this.setupResizeObserver();
117
135
  }
118
136
  }
119
137
 
120
- bindAutoRenewEvent() {
121
- // dispatched this event from timer-countdown
122
- this.addEventListener('autoRenewAttempt', async event => {
123
- const isPageFlipped = event.detail.bookPageChange;
124
-
125
- this.autoRenewObj = await new OneHourAutoRenew(
126
- isPageFlipped,
127
- this.identifier,
128
- this.localCache,
129
- this.autoRenewConfig,
130
- this.lendingStatus.user_has_browsed && !this.lendingStatus.browsingExpired
131
- );
132
-
133
- this.toastTexts = this.autoRenewObj.toastTexts;
134
- this.hideToast = this.autoRenewObj.hideToast;
135
- this.browseAgainNow = this.autoRenewObj.renewNow;
136
- if (this.browseAgainNow) {
137
- await this.browseHasRenew();
138
- }
139
- });
140
- }
141
-
142
- async browseHasExpired() {
143
- const currStatus = { ...this.lendingStatus, browsingExpired: true };
144
- this.lendingStatus = currStatus;
145
-
146
- // remove respected key:value
147
- await this.localCache.delete(`${this.identifier}-loanTime`);
148
- await this.localCache.delete(`${this.identifier}-pageFlipTime`);
149
-
150
- // show message after browsed book is expired.
151
- this.toastTexts = 'This book has been auto-returned due to inactivity.';
152
- }
153
-
154
- async browseHasRenew() {
155
- const currStatus = {
156
- ...this.lendingStatus,
157
- user_has_browsed: true,
158
- browsingExpired: false,
159
- secondsLeftOnLoan: this.autoRenewConfig.totalTime + 1,
160
- };
161
- this.lendingStatus = currStatus;
162
-
163
- this.startBrowseTimer();
164
- }
165
-
166
- startBrowseTimer() {
167
- clearTimeout(this.browserTimer);
168
-
169
- const {
170
- browsingExpired,
171
- user_has_browsed,
172
- secondsLeftOnLoan,
173
- } = this.lendingStatus;
174
- if (!user_has_browsed || browsingExpired) {
175
- return;
176
- }
177
-
178
- // expired book and show browse again button
179
- const timeLeft = secondsLeftOnLoan * 1000;
180
- this.browserTimer = setTimeout(() => {
181
- this.browseHasExpired();
182
- }, timeLeft);
183
- }
184
-
185
138
  /** SharedObserver resize handler */
186
139
  handleResize(entry) {
187
140
  // if you are observing multiple targets,
@@ -215,6 +168,8 @@ export default class IABookActions extends LitElement {
215
168
  /** End SharedObserver resize handler */
216
169
 
217
170
  async setupLendingToolbarActions() {
171
+ this.suppressToast = false;
172
+
218
173
  this.lendingOptions = new GetLendingActions(
219
174
  this.userid,
220
175
  this.identifier,
@@ -235,13 +190,14 @@ export default class IABookActions extends LitElement {
235
190
  });
236
191
 
237
192
  this.borrowType = actions.borrowType;
238
- this.remainingTime = this.lendingStatus.secondsLeftOnLoan;
239
193
 
240
194
  const hasExpired =
241
195
  'browsingExpired' in this.lendingStatus &&
242
196
  this.lendingStatus?.browsingExpired;
243
197
  if (hasExpired) {
244
- window?.Sentry?.captureMessage('setupLendingToolbarActions hasExpired');
198
+ if (!this.tokenPoller) {
199
+ window?.Sentry?.captureMessage(sentryLogs.bookWasExpired);
200
+ }
245
201
  this.tokenPoller?.disconnectedInterval();
246
202
  /** Global event - always fire */
247
203
  this.dispatchEvent(
@@ -251,12 +207,13 @@ export default class IABookActions extends LitElement {
251
207
  composed: true,
252
208
  })
253
209
  );
210
+
211
+ // early return if book is already expired
254
212
  return;
255
213
  }
256
214
 
257
215
  if (this.borrowType === 'browsed') {
258
216
  // start timer for browsed.
259
- // when browse is completed, we shows browse-again button
260
217
  this.startBrowseTimer();
261
218
  }
262
219
 
@@ -266,7 +223,212 @@ export default class IABookActions extends LitElement {
266
223
  return;
267
224
  }
268
225
 
269
- this.startLoanTokenPoller();
226
+ // initial timer state for 1-hour loan
227
+ if (this.borrowType === 'browsed' && !this.loanRenewResult.renewNow) {
228
+ setTimeout(() => {
229
+ this.resetTimerCountState();
230
+ }, 100);
231
+ }
232
+
233
+ /**
234
+ * tokenPoller determines if user has loan token for this book
235
+ * - if book is going to renew, need to wait until renew is completed
236
+ * - otherwise execute immediately
237
+ */
238
+ setTimeout(
239
+ () => {
240
+ this.startLoanTokenPoller();
241
+ },
242
+
243
+ // if book is renew while reading, let's wait to execute create-token api
244
+ this.loanRenewResult.renewNow ? this.tokenDelay * 1000 : 100
245
+ );
246
+ }
247
+
248
+ /**
249
+ * Bind 1 hour loan auto renew event,
250
+ * There are two events we want to use,
251
+ * 1. BookReader:userAction - dispatched from bookreader side
252
+ * 2. click event to refresh the page when book is auto expired
253
+ * 3. IABookActions:loanRenew - dispatched from timer-countdown component
254
+ */
255
+ bindLoanRenewEvents() {
256
+ /**
257
+ * dispatched this event from bookreader page changed
258
+ */
259
+ window.addEventListener('BookReader:userAction', () => {
260
+ if (this.borrowType === 'browsed') {
261
+ console.log('user-action executed!');
262
+ this.autoLoanRenewChecker(true);
263
+ }
264
+
265
+ return nothing;
266
+ });
267
+
268
+ /**
269
+ * detect click-event on document to close toast-template
270
+ */
271
+ document.addEventListener('click', e => {
272
+ if (this.loanRenewHelper && this.loanRenewResult.secondsLeft > 0) {
273
+ console.log('clicked-outside');
274
+ this.suppressToast = true;
275
+ }
276
+
277
+ // reload when user click on book-page and book is EXPIRED
278
+ const hasExpired =
279
+ 'browsingExpired' in this.lendingStatus &&
280
+ this.lendingStatus?.browsingExpired;
281
+ if (hasExpired && e.target.nodeName !== 'IA-BOOK-ACTIONS') {
282
+ window.location?.reload();
283
+ }
284
+ });
285
+
286
+ /**
287
+ * this event dispatched from timer-countdown component for:
288
+ * 1. user turned book page after showing auto-returned warning message
289
+ * 2. show warning message having remaining time
290
+ * @see TimerCountdown::timerCountdown
291
+ */
292
+ this.addEventListener('IABookActions:loanRenew', async event => {
293
+ await this.autoLoanRenewChecker(false);
294
+
295
+ // show warning message with remaining time to auto returned it.
296
+ if (this.loanRenewResult.renewNow === false) {
297
+ this.loanRenewResult.secondsLeft = event.detail.secondsLeft;
298
+ this.showToastMessage();
299
+ }
300
+ });
301
+ }
302
+
303
+ /**
304
+ * To determine if need to be renewed browsed book
305
+ * @see LoanRenewHelper
306
+ *
307
+ * @param {Boolean} hasPageChanged
308
+ */
309
+ async autoLoanRenewChecker(hasPageChanged = false) {
310
+ this.loanRenewHelper = new LoanRenewHelper(
311
+ hasPageChanged,
312
+ this.identifier,
313
+ this.localCache,
314
+ this.loanRenewTimeConfig
315
+ );
316
+
317
+ await this.loanRenewHelper.handleLoanRenew();
318
+ this.loanRenewResult = this.loanRenewHelper.result;
319
+ }
320
+
321
+ /**
322
+ * Show toast messages on some specific loan renew features. e.g.
323
+ * - show message when book is auto renewed
324
+ * - show message when book is expired
325
+ * - show message having remaining time when book is about to auto returned
326
+ */
327
+ async showToastMessage() {
328
+ if (this.suppressToast) return;
329
+
330
+ const iaBookActions = document.querySelector('ia-book-actions')?.shadowRoot;
331
+ if (!iaBookActions) return;
332
+
333
+ let toastTemplate = iaBookActions.querySelector('toast-template');
334
+ if (!toastTemplate) {
335
+ toastTemplate = document.createElement('toast-template');
336
+ }
337
+ await iaBookActions.appendChild(toastTemplate);
338
+
339
+ const config = new ToastConfig();
340
+ config.dismisOnClick = true;
341
+ config.texts = this.loanRenewHelper?.getMessageTexts(
342
+ this.loanRenewResult.texts,
343
+ this.loanRenewResult.secondsLeft
344
+ );
345
+
346
+ toastTemplate.showToast({
347
+ config,
348
+ });
349
+ }
350
+
351
+ async browseHasRenew() {
352
+ const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
353
+ const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
354
+
355
+ const currStatus = {
356
+ ...this.lendingStatus,
357
+ user_has_browsed: true,
358
+ browsingExpired: false,
359
+ secondsLeftOnLoan: secondsLeft,
360
+ };
361
+ this.lendingStatus = currStatus;
362
+
363
+ this.startBrowseTimer();
364
+ }
365
+
366
+ startBrowseTimer() {
367
+ clearTimeout(this.browseTimer);
368
+ const {
369
+ browsingExpired,
370
+ user_has_browsed,
371
+ secondsLeftOnLoan,
372
+ } = this.lendingStatus;
373
+ if (!user_has_browsed || browsingExpired) {
374
+ return;
375
+ }
376
+
377
+ this.browseTimer = setTimeout(() => {
378
+ this.browseHasExpired();
379
+ }, secondsLeftOnLoan * 1000);
380
+ }
381
+
382
+ /**
383
+ * Execute when loan is expired
384
+ */
385
+ async browseHasExpired() {
386
+ this.tokenPoller?.disconnectedInterval();
387
+
388
+ const currStatus = { ...this.lendingStatus, browsingExpired: true };
389
+ this.lendingStatus = currStatus;
390
+
391
+ // remove respected key:value for loan-renew
392
+ await this.localCache.delete(`${this.identifier}-loanTime`);
393
+ await this.localCache.delete(`${this.identifier}-pageChangedTime`);
394
+
395
+ // show message after browsed book is expired.
396
+ this.loanRenewResult.renewNow = false;
397
+ this.loanRenewResult.texts =
398
+ 'This book has been automatically returned due to inactivity.';
399
+
400
+ this.suppressToast = false;
401
+ this.showToastMessage();
402
+
403
+ window?.Sentry?.captureMessage(sentryLogs.browseHasExpired);
404
+ console.log(sentryLogs.browseHasExpired);
405
+ }
406
+
407
+ /**
408
+ * Reset timer animation state after book renewed
409
+ */
410
+ async resetTimerCountState() {
411
+ const timerCountdown = this._shadowRoot.querySelector('timer-countdown');
412
+ if (!timerCountdown) return;
413
+
414
+ const secondsLeft = Number(this.lendingStatus.secondsLeftOnLoan);
415
+ const strokeDashOffset =
416
+ (secondsLeft / this.loanRenewTimeConfig.loanTotalTime) * 315;
417
+
418
+ // set seconds left in loan expire
419
+ timerCountdown.style?.setProperty('--secondsLeftOnLoan', `${secondsLeft}s`);
420
+
421
+ // set circle stroke offset left in loan expire
422
+ timerCountdown.style?.setProperty(
423
+ '--strokeLeftOnLoan',
424
+ `${Number(strokeDashOffset)}` // the perimeter of the circle = (π * 2 * radius)
425
+ );
426
+
427
+ const animationCircle = timerCountdown.shadowRoot.querySelector('.circle');
428
+ animationCircle.style.animationName = 'none';
429
+ setTimeout(() => {
430
+ animationCircle.style.animationName = 'circletimer';
431
+ }, 100);
270
432
  }
271
433
 
272
434
  render() {
@@ -291,26 +453,15 @@ export default class IABookActions extends LitElement {
291
453
  get timerCountdownTemplate() {
292
454
  return this.borrowType === 'browsed'
293
455
  ? html`<timer-countdown
294
- time=${Number(this.remainingTime)}
295
- .autoCheckAt=${this.autoRenewConfig.autoCheckAt}
296
- ?resetTimerCountdown=${this.resetTimerCountdown}
456
+ .secondsLeftOnLoan=${Number(this.lendingStatus.secondsLeftOnLoan)}
457
+ .loanRenewAtLast=${this.loanRenewTimeConfig.loanRenewAtLast}
458
+ .isDevBox=${this.loanRenewTimeConfig.isDevBox}
297
459
  ></timer-countdown>`
298
460
  : nothing;
299
461
  }
300
462
 
301
- get toastMessageTemplate() {
302
- return html`
303
- <toast-message
304
- .texts=${this.toastTexts}
305
- ?dismisOnClick=${true}
306
- ?hideToast=${this.hideToast}
307
- ></toast-message>
308
- `;
309
- }
310
-
311
463
  get bookActionBar() {
312
464
  return html`
313
- <button @click=${() => this.pageFlipEvent()}>Page Flip</button>
314
465
  <collapsible-action-group
315
466
  .userid=${this.userid}
316
467
  .identifier=${this.identifier}
@@ -320,39 +471,56 @@ export default class IABookActions extends LitElement {
320
471
  .width=${this.width}
321
472
  .borrowType=${this.borrowType}
322
473
  .returnUrl=${this.returnUrl}
323
- .autoRenew=${this.autoRenew}
324
- .autoRenewConfig=${this.autoRenewConfig}
474
+ .localCache=${this.localCache}
475
+ .loanTotalTime=${this.loanRenewTimeConfig.loanTotalTime}
325
476
  ?hasAdminAccess=${this.hasAdminAccess}
326
477
  ?disabled=${this.disableActionGroup}
327
- ?browseAgainNow=${this.browseAgainNow}
478
+ ?renewNow=${this.loanRenewResult.renewNow}
479
+ @loanAutoRenewed=${this.handleLoanAutoRenewed}
328
480
  @lendingActionError=${this.handleLendingActionError}
329
481
  @toggleActionGroup=${this.handleToggleActionGroup}
330
482
  >
331
483
  </collapsible-action-group>
332
484
  ${this.textGroupTemplate} ${this.infoIconTemplate}
333
- ${this.timerCountdownTemplate} ${this.toastMessageTemplate}
485
+ ${this.timerCountdownTemplate}
334
486
  `;
335
487
  }
336
488
 
337
- // will move this function to bookreader...
338
- async pageFlipEvent() {
339
- try {
340
- // dispatch event to say book page has flipped
341
- document.querySelector("ia-book-actions").dispatchEvent(
342
- new CustomEvent("autoRenewAttempt", {
343
- detail: { bookPageChange: true },
344
- })
345
- );
346
- } catch (error) { console.log(error) }
489
+ /**
490
+ * Execute after auto loan renewed is completed
491
+ * - show success message
492
+ * - then change the remaining time
493
+ * - reset timer state
494
+ */
495
+ async handleLoanAutoRenewed() {
496
+ if (this.loanRenewResult.renewNow) {
497
+ this.tokenPoller?.disconnectedInterval();
498
+
499
+ this.suppressToast = false;
500
+ await this.showToastMessage();
501
+ await this.browseHasRenew();
502
+ await this.resetTimerCountState();
503
+
504
+ window?.Sentry?.captureMessage(`${sentryLogs.bookHasRenewed}`);
505
+ // analytics?? for consecutive renew.....
506
+
507
+ // testing console....
508
+ console.log(sentryLogs.bookHasRenewed, {
509
+ loanRenewResult: this.loanRenewResult,
510
+ browseHasRenew: this.lendingStatus.secondsLeftOnLoan,
511
+ resetTimerCountState: this._shadowRoot.querySelector('timer-countdown'),
512
+ });
513
+ }
347
514
  }
348
515
 
349
516
  /**
350
517
  * enable access of borrowed/browsed books
518
+ * @see LoanTokenPoller
351
519
  */
352
520
  startLoanTokenPoller() {
353
521
  if (this.tokenPoller) {
354
- window?.Sentry?.captureMessage('startLoanTokenPoller clearing interval');
355
- this.tokenPoller.disconnectedInterval();
522
+ window?.Sentry?.captureMessage(sentryLogs.clearTokenPoller);
523
+ this.tokenPoller?.disconnectedInterval();
356
524
  }
357
525
  const successCallback = () => {
358
526
  this.lendingBarPostInit();
@@ -377,7 +545,7 @@ export default class IABookActions extends LitElement {
377
545
  this.borrowType,
378
546
  successCallback,
379
547
  errorCallback,
380
- this.tokenDelay // 1000 ms = 1 sec
548
+ this.tokenDelay // in seconds
381
549
  );
382
550
  }
383
551
 
@@ -408,6 +576,20 @@ export default class IABookActions extends LitElement {
408
576
 
409
577
  if (errorMsg) this.showErrorModal(errorMsg, action);
410
578
 
579
+ // if error related to loan token
580
+ // - clear tokenPoller interval
581
+ // - set user_has_browsed to `false`
582
+ if (action === 'create_token') {
583
+ this.tokenPoller?.disconnectedInterval();
584
+
585
+ const currStatus = {
586
+ ...this.lendingStatus,
587
+ user_has_browsed: false,
588
+ available_to_browse: true,
589
+ };
590
+ this.lendingStatus = currStatus;
591
+ }
592
+
411
593
  // update action bar state if book is not available to browse or borrow.
412
594
  if (errorMsg && errorMsg.match(/not available to borrow/gm)) {
413
595
  let currStatus = this.lendingStatus;
@@ -463,7 +645,8 @@ export default class IABookActions extends LitElement {
463
645
  href="mailto:info@archive.org?subject=Help: cannot access my borrowed book: ${this
464
646
  .identifier}"
465
647
  >info@archive.org</a
466
- >`;
648
+ ><br /><br />
649
+ errorLog: ${errorMsg}`;
467
650
  }
468
651
 
469
652
  this.modal.showModal({
@@ -484,11 +667,13 @@ export default class IABookActions extends LitElement {
484
667
  }
485
668
 
486
669
  get textGroupTemplate() {
487
- return html`<text-group
488
- textClass=${this.textClass}
489
- texts=${this.primaryTitle}
490
- >
491
- </text-group>`;
670
+ return this.primaryTitle
671
+ ? html`<text-group
672
+ textClass=${this.textClass}
673
+ .texts=${this.primaryTitle}
674
+ >
675
+ </text-group>`
676
+ : nothing;
492
677
  }
493
678
 
494
679
  get hasAdminAccess() {
@@ -499,20 +684,23 @@ export default class IABookActions extends LitElement {
499
684
  return css`
500
685
  :host {
501
686
  display: block;
502
- background: var(--primaryBGColor, #000);
503
- color: var(--primaryTextColor, #fff);
504
687
  }
688
+
505
689
  .lending-wrapper {
506
690
  width: 100%;
507
691
  margin: 0 auto;
692
+ background: var(--primaryBGColor, #000);
693
+ color: var(--primaryTextColor, #fff);
508
694
  display: inline-flex;
509
695
  align-items: center;
510
696
  justify-content: center;
511
697
  flex-wrap: wrap;
512
698
  }
513
699
 
514
- toast-message {
515
- --messageHeightFromTop: 18%;
700
+ toast-template {
701
+ --toastTopMargin: 80px;
702
+ --toastBGColor: #333;
703
+ --toastFontColor: #fff;
516
704
  }
517
705
  `;
518
706
  }
@@ -6,7 +6,7 @@ const container = ({
6
6
  {
7
7
  analyticsEvent: { action: 'Browse', category: 'Lending' },
8
8
  className: 'ia-button primary',
9
- text: 'Borrow for 1 hour',
9
+ text: 'Borrow',
10
10
  id: 'browseBook',
11
11
  },
12
12
  {
@@ -40,7 +40,7 @@ describe('<collapsible-action-group>', () => {
40
40
  .true;
41
41
 
42
42
  const primaryButton = primaryActionContainer.querySelector('.ia-button');
43
- expect(primaryButton.innerText).to.equal('Borrow for 1 hour');
43
+ expect(primaryButton.innerText).to.equal('Borrow');
44
44
  });
45
45
 
46
46
  it('check if loader is active and action-group is disabled', async () => {