@internetarchive/ia-book-actions 0.0.29-alpha21 → 0.0.29-alpha23

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.29-alpha21",
3
+ "version": "0.0.29-alpha23",
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/local-cache": "^0.2.0",
23
23
  "@internetarchive/modal-manager": "^0.2.1",
24
24
  "@internetarchive/shared-resize-observer": "^0.2.0",
25
- "@internetarchive/toast-manager": "0.0.1-alpha8",
25
+ "@internetarchive/toast-manager": "0.0.1-alpha9",
26
26
  "lit": "^2.5.0"
27
27
  },
28
28
  "devDependencies": {
@@ -118,7 +118,7 @@ export const canBrowseAndBorrow = {
118
118
  loanStartDate: '2021-07-30 09:57:40',
119
119
  loansUrl: '/details/@neeraj-archive?tab=loans#loans-on-loan',
120
120
  maxLoans: 10,
121
- secondsLeftOnLoan: 3591,
121
+ secondsLeftOnLoan: 12,
122
122
  shouldProtectImages: true,
123
123
  totalWaitlistCount: 0,
124
124
  userHasBorrowed: false,
@@ -49,12 +49,6 @@ export class InfoIcon extends LitElement {
49
49
  vertical-align: middle;
50
50
  background: white;
51
51
  }
52
- .more-info-icon.mobile {
53
- position: absolute;
54
- top: 4px;
55
- right: 55px;
56
- margin-top: 15px;
57
- }
58
52
  .hidden {
59
53
  display: none;
60
54
  }
@@ -58,55 +58,53 @@ export default class TimerCountdown extends LitElement {
58
58
  render() {
59
59
  return html`
60
60
  <svg
61
- width="30"
62
- height="30"
61
+ width="16"
62
+ height="16"
63
63
  viewBox="0 0 100 100"
64
64
  xmlns="http://www.w3.org/2000/svg"
65
65
  >
66
66
  <circle class="circle" cx="50" cy="50" r="50" />
67
67
  </svg>
68
+ <span>${Math.round(this.time)}</span>
68
69
  `;
69
70
  }
70
71
 
71
72
  static get styles() {
72
73
  const white = css`var(--white, #fff)`;
73
- const secondsLeft = css`var(--secondsLeft, 60s)`;
74
+ const timerSecondsLeft = css`var(--timerSeconds, 6000s)`;
75
+ const timerStrokeLeft = css`var(--timerStroke, 315)`;
74
76
 
75
77
  return css`
76
78
  :host {
77
79
  right: 5px;
78
- font-size: 14px;
79
80
  position: absolute;
80
81
  }
81
82
 
82
83
  @keyframes circletimer {
83
84
  0% {
84
- stroke-dashoffset: 320;
85
- stroke-dasharray: 320;
85
+ stroke-dashoffset: ${timerStrokeLeft};
86
+ stroke-dasharray: 315;
86
87
  }
87
88
  100% {
88
89
  stroke-dashoffset: 0;
89
- stroke-dasharray: 320;
90
+ stroke-dasharray: 315;
90
91
  }
91
92
  }
92
93
 
93
94
  svg {
94
- background-color: transparent;
95
- position: absolute;
96
- top: 50%;
97
- right: 0;
95
+ background-color: ${white};
98
96
  border-radius: 50px;
99
97
  border: 2px solid ${white};
100
- transform: translate(-50%, -50%) rotateZ(-90deg);
98
+ transform: rotateZ(-90deg);
101
99
  }
102
100
 
103
101
  svg .circle {
104
- stroke: ${white};
102
+ stroke: #000;
105
103
  stroke-width: 100px;
106
- fill: transparent;
107
- stroke-dashoffset: 320;
104
+ fill: ${white};
105
+ stroke-dashoffset: 315;
108
106
  stroke-dasharray: 0;
109
- animation: ${secondsLeft} circletimer linear;
107
+ animation: ${timerSecondsLeft} circletimer linear;
110
108
  }
111
109
  `;
112
110
  }
@@ -36,7 +36,7 @@ export default class ActionsConfig {
36
36
  firstBrowseConfig() {
37
37
  return {
38
38
  id: 'browseBook',
39
- text: 'Borrow for 1 hour',
39
+ text: 'Borrow', // changed texts from 'Borrow for 1 hour' to 'Borrow'
40
40
  className: 'primary',
41
41
  analyticsEvent: {
42
42
  category: this.analyticsCategories.preview,
@@ -48,7 +48,7 @@ export default class ActionsConfig {
48
48
  browseAgainConfig() {
49
49
  return {
50
50
  id: 'browseBookAgain',
51
- text: 'Borrow again',
51
+ text: 'Borrow', // changed texts fro 'Borrow again' to 'Borrow'
52
52
  className: 'primary',
53
53
  analyticsEvent: {
54
54
  category: this.analyticsCategories.browse,
@@ -5,8 +5,9 @@ import { ToastConfig } from '@internetarchive/toast-manager';
5
5
  * This class is used to determine if use is eligible for auto renew loan.
6
6
  */
7
7
  export class LoanRenewHelper {
8
- constructor(hasPageChanged, identifier, localCache, loanRenewConfig) {
8
+ constructor(hasPageChanged, hideToast, identifier, localCache, loanRenewConfig) {
9
9
  this.hasPageChanged = hasPageChanged;
10
+ this.hideToast = hideToast;
10
11
  this.identifier = identifier;
11
12
  this.localCache = localCache;
12
13
  this.loanRenewConfig = loanRenewConfig;
@@ -64,6 +65,7 @@ export class LoanRenewHelper {
64
65
  if (currentTime >= lastTimeFrame) {
65
66
  this.result.texts = this.loanRenewMessage;
66
67
  this.result.renewNow = true;
68
+ console.log('manually renewed by page click!');
67
69
  }
68
70
 
69
71
  this.setPageChangedTime();
@@ -97,9 +99,11 @@ export class LoanRenewHelper {
97
99
  this.result.texts = this.loanReturnWarning;
98
100
  this.result.renewNow = false; // not viewed
99
101
  this.showToastMessage();
102
+ console.log('not viewed!');
100
103
  } else if (lastPageFlipTime >= lastFlipTimeFrame) {
101
104
  this.result.texts = '';
102
105
  this.result.renewNow = true; // viewed in last time frame
106
+ console.log('silently renewed!');
103
107
  }
104
108
 
105
109
  return this.result;
@@ -123,6 +127,8 @@ export class LoanRenewHelper {
123
127
  * - show warninig msg when book is about to auto returned
124
128
  */
125
129
  async showToastMessage() {
130
+ if (this.hideToast) return false;
131
+
126
132
  const iaBookActions = document.querySelector('ia-book-actions').shadowRoot;
127
133
  let toastTemplate = iaBookActions.querySelector('toast-template');
128
134
  if (!toastTemplate) {
@@ -148,7 +154,7 @@ export class LoanRenewHelper {
148
154
  * @returns {Object} Date
149
155
  */
150
156
  changeTime(date, minutes, op) {
151
- if (date === undefined) return nothing;
157
+ if (date === undefined) return null;
152
158
 
153
159
  if (op === 'sub') {
154
160
  return new Date(date.getTime() - minutes * 1000);
@@ -73,6 +73,7 @@ export default class IABookActions extends LitElement {
73
73
  // loan auto renew
74
74
  this.browserTimer = undefined;
75
75
  this.loanRenewConfig = {};
76
+ this.hideToast = false;
76
77
 
77
78
  /**
78
79
  * contains loan auto-renew response
@@ -232,15 +233,20 @@ export default class IABookActions extends LitElement {
232
233
  */
233
234
  bindLoanRenewEvents() {
234
235
  // dispatched this event from bookreader page changed
235
- window.addEventListener('BookReader:pageChanged', () => {
236
- // early return if book is not browsed (1 hour borrow)
237
- if (this.borrowType === 'browsed') {
236
+ window.addEventListener('BookReader:pageChanged', event => {
237
+ if (this.borrowType === 'browsed' && event.detail.hasPageChanged) {
238
238
  this.autoLoanRenewChecker(true);
239
239
  }
240
240
 
241
241
  return nothing;
242
242
  });
243
243
 
244
+ document.addEventListener('click', () => {
245
+ if (this.loanRenewHelper && this.loanRenewHelper.result.renewNow === false) {
246
+ this.hideToast = true;
247
+ }
248
+ });
249
+
244
250
  /**
245
251
  * this event dispatched from timer-countdown component for:
246
252
  * 1. user turned book page after showing auto-returned warning message
@@ -262,12 +268,14 @@ export default class IABookActions extends LitElement {
262
268
  async autoLoanRenewChecker(hasPageChanged = false) {
263
269
  this.loanRenewHelper = new LoanRenewHelper(
264
270
  hasPageChanged,
271
+ this.hideToast,
265
272
  this.identifier,
266
273
  this.localCache,
267
274
  this.loanRenewConfig
268
275
  );
269
276
 
270
277
  await this.loanRenewHelper.handleLoanRenew();
278
+ console.log(this.loanRenewResult);
271
279
  this.loanRenewResult = this.loanRenewHelper.result;
272
280
  }
273
281
 
@@ -327,12 +335,26 @@ export default class IABookActions extends LitElement {
327
335
  * Reset timer animation state after book renewed
328
336
  */
329
337
  async resetTimerCountState() {
338
+ const secondsLeft = Number(this.lendingStatus.secondsLeftOnLoan);
339
+
330
340
  const timerCountdown = this.shadowRoot.querySelector('timer-countdown');
331
341
  const animationCircle = timerCountdown.shadowRoot.querySelector('.circle');
332
342
 
343
+ // the perimeter of the circle
344
+ const circleStroke = 315; // (π * 2 * radius)
345
+ const strokeDashOffset =
346
+ (secondsLeft / this.loanRenewConfig.totalTime) *
347
+ circleStroke;
348
+
349
+ // set seconds left in loan expire
350
+ timerCountdown.style?.setProperty(
351
+ '--timerSeconds',
352
+ `${secondsLeft}s`
353
+ );
354
+ // set circle stroke offset left in loan expire
333
355
  timerCountdown.style?.setProperty(
334
- '--secondsLeft',
335
- `${Number(this.lendingStatus.secondsLeftOnLoan)}s`
356
+ '--timerStroke',
357
+ `${Number(strokeDashOffset)}`
336
358
  );
337
359
 
338
360
  animationCircle.style.animationName = 'none';
@@ -403,6 +425,7 @@ export default class IABookActions extends LitElement {
403
425
  */
404
426
  async handleLoanAutoRenewed() {
405
427
  if (this.loanRenewResult.renewNow) {
428
+ this.hideToast = false;
406
429
  this.tokenPoller.disconnectedInterval();
407
430
  await this.loanRenewHelper.showToastMessage();
408
431
  await this.browseHasRenew();
@@ -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 () => {
@@ -25,7 +25,7 @@ describe('Get Lending Actions', () => {
25
25
 
26
26
  expect(actions.primaryTitle).to.equal(bookTitles.available_1hr);
27
27
  expect(actions.primaryActions.length).to.equal(3);
28
- expect(actions.primaryActions[0].text).to.equal('Borrow for 1 hour');
28
+ expect(actions.primaryActions[0].text).to.equal('Borrow');
29
29
  expect(actions.primaryActions[1].text).to.equal('Borrow for 14 days');
30
30
  expect(actions.secondaryActions[1].text).to.equal('Purchase at');
31
31
  });
@@ -111,7 +111,7 @@ describe('Get Lending Actions', () => {
111
111
  expect(actions.primaryTitle).to.equal(bookTitles.claim_waitlist);
112
112
  expect(actions.primaryActions.length).to.equal(3);
113
113
  expect(actions.primaryActions[0].text).to.equal('Borrow for 14 days');
114
- expect(actions.primaryActions[1].text).to.equal('Borrow for 1 hour');
114
+ expect(actions.primaryActions[1].text).to.equal('Borrow');
115
115
  expect(actions.primaryActions[2].text).to.equal('Leave Waitlist');
116
116
  expect(spy.called).to.be.true;
117
117
  });
@@ -138,7 +138,7 @@ describe('Get Lending Actions', () => {
138
138
  expect(actions.primaryTitle).to.equal(bookTitles.on_waitlist);
139
139
  expect(actions.primaryActions.length).to.equal(2);
140
140
  expect(actions.primaryActions[0].text).to.equal('Leave Waitlist');
141
- expect(actions.primaryActions[1].text).to.equal('Borrow for 1 hour');
141
+ expect(actions.primaryActions[1].text).to.equal('Borrow');
142
142
  expect(claimSpy.called).to.be.false;
143
143
  expect(waitlistSpy.called).to.be.true;
144
144
  });
@@ -162,7 +162,7 @@ describe('Get Lending Actions', () => {
162
162
  expect(actions.primaryTitle).to.equal(bookTitles.on_waitlist);
163
163
  expect(actions.primaryActions.length).to.equal(2);
164
164
  expect(actions.primaryActions[0].text).to.equal('Leave Waitlist');
165
- expect(actions.primaryActions[1].text).to.equal('Borrow for 1 hour');
165
+ expect(actions.primaryActions[1].text).to.equal('Borrow');
166
166
  expect(waitlistSpy.called).to.be.true;
167
167
  });
168
168
  });
@@ -81,7 +81,7 @@ describe('Primary Actions data', () => {
81
81
  );
82
82
  const expectedPrimaryActions = [
83
83
  {
84
- text: 'Borrow for 1 hour',
84
+ text: 'Borrow', // changed from 'Borrow for 1 hour'
85
85
  callback: () => {},
86
86
  className: 'ia-button primary',
87
87
  },
@@ -161,7 +161,7 @@ describe('Borrow status actions', () => {
161
161
 
162
162
  // removed available_to_borrow from lending bar
163
163
  expect(el.lendingStatus.available_to_borrow).to.be.false;
164
- expect(el.primaryActions[0].text).to.equal('Borrow for 1 hour');
164
+ expect(el.primaryActions[0].text).to.equal('Borrow');
165
165
  });
166
166
 
167
167
  it('Check action for borrowable book without user', async () => {
@@ -251,7 +251,7 @@ describe('Browsing expired status', () => {
251
251
  await aTimeout(1500); // wait for 1.5 second
252
252
  await el.updateComplete;
253
253
 
254
- expect(el.primaryActions[0].text).to.equal('Borrow again');
254
+ expect(el.primaryActions[0].text).to.equal('Borrow');
255
255
  });
256
256
 
257
257
  it('Expiring book cancels interval & emits event', async () => {
@@ -286,7 +286,7 @@ describe('Browsing expired status', () => {
286
286
  await aTimeout(1500); // wait for 1.5 sec
287
287
 
288
288
  expect(eventReceived).to.equal(true);
289
- expect(el.primaryActions[0].text).to.equal('Borrow again');
289
+ expect(el.primaryActions[0].text).to.equal('Borrow');
290
290
  expect(el.tokenPoller.loanTokenInterval).to.equal(undefined);
291
291
  });
292
292
  });