@internetarchive/ia-book-actions 0.0.29-alpha9 → 0.0.29-beta2

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
@@ -87,18 +87,13 @@
87
87
 
88
88
  <script type="module">
89
89
  /* eslint-disable */
90
+
90
91
  import '../src/ia-book-actions.js';
91
92
  import {
92
93
  defaultLendingStatus,
93
94
  canBrowseAndBorrow,
94
95
  } from '../src/assets/data/lending-get-status-service.js';
95
96
  import { ModalConfig } from '@internetarchive/modal-manager';
96
- import { LocalCache } from '@internetarchive/local-cache';
97
-
98
- const localCache = new LocalCache({
99
- namespace: '1HourLoanStorage',
100
- defaultTTL: 1 * 60, // 1 minute
101
- });
102
97
 
103
98
  const userid = '@neeraj-archive';
104
99
  const identifier = 'naturalhistoryof00unse_4111';
@@ -126,15 +121,8 @@
126
121
  iaBookActions.lendingBarPostInit = lendingBarPostInit;
127
122
  iaBookActions.tokenDelay = 2000; // 2 seconds
128
123
  iaBookActions.returnUrl = 'https://openlibrary.org';
129
- iaBookActions.localCache = localCache;
130
- iaBookActions.autoRenewConfig = {
131
- totalTime: 60, // 60 second = 1 min
132
- autoCheckAt: 55, // totalTime - 10th minute
133
- FlippedInLast: 15, // within last 15 second/minute
134
- };
135
124
 
136
125
  let lendingStatus1 = iaBookActions.lendingStatus;
137
- let secondsLeftOnLoan = iaBookActions.autoRenewConfig.totalTime;
138
126
 
139
127
  document.querySelectorAll('.titleBar input[type=checkbox]').forEach((item) => {
140
128
  item.addEventListener('click', (e) => {
@@ -146,18 +134,22 @@
146
134
  });
147
135
  });
148
136
 
149
- document.querySelectorAll('.autoRenew input[type=checkbox]').forEach((item) => {
137
+ document.querySelectorAll('.searchParam input[type=checkbox]').forEach((item) => {
150
138
  item.addEventListener('click', (e) => {
139
+ var searchParams = new URLSearchParams(window.location.search);
140
+ var separate = '';
151
141
  if (e.target.checked) {
152
- iaBookActions.autoRenew = true;
153
- iaBookActions.resetTimerCountdown = true;
154
- lendingStatus1.secondsLeftOnLoan = secondsLeftOnLoan;
142
+ separate = '?';
143
+ searchParams.set('q', 'test');
155
144
  } else {
156
- iaBookActions.autoRenew = false;
145
+ separate = '';
146
+ searchParams.delete('q');
157
147
  }
158
148
 
159
- let lending = {...defaultLendingStatus, ...lendingStatus1};
160
- iaBookActions.lendingStatus = lending;
149
+ if (history.pushState) {
150
+ var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + separate + searchParams;
151
+ window.history.pushState({path:newurl},'',newurl);
152
+ }
161
153
  });
162
154
  });
163
155
 
@@ -214,24 +206,12 @@
214
206
  });
215
207
 
216
208
  document.querySelectorAll('.availableToBrowse input[type=radio]').forEach((item) => {
217
- item.addEventListener('click', async (e) => {
209
+ item.addEventListener('click', (e) => {
218
210
  if (e.target.value === 'user_has_browsed') {
219
211
  lendingStatus1.user_has_browsed = true;
220
212
  lendingStatus1.available_to_browse = false;
221
- lendingStatus1.secondsLeftOnLoan = secondsLeftOnLoan;
213
+ lendingStatus1.secondsLeftOnLoan = 10;
222
214
  lendingStatus1.browsingExpired = false;
223
-
224
- try {
225
- // set a value
226
- await localCache.set({
227
- key: `${identifier}-loanTime`,
228
- value: new Date(), // current time
229
- ttl: Number(iaBookActions.autoRenewConfig.totalTime),
230
- })
231
-
232
- await localCache.delete(`${identifier}-pageFlipTime`);
233
- } catch (error) {}
234
-
235
215
  } else if(e.target.value === 'browsingExpired') {
236
216
  lendingStatus1.user_has_browsed = true;
237
217
  lendingStatus1.available_to_browse = false;
@@ -302,6 +282,9 @@
302
282
  <td class="titleBar">
303
283
  <label><input type="checkbox" name="title" value="title" />Title Bar</label>
304
284
  </td>
285
+ <td class="searchParam">
286
+ <label><input type="checkbox" name="search" value="Search Param" />Search Param</label>
287
+ </td>
305
288
  </tr>
306
289
  </table>
307
290
  </fieldset>
@@ -311,7 +294,6 @@
311
294
  <table class="initial">
312
295
  <tr colspan='5'>
313
296
  <td class="errorEnable"><label><input type="checkbox" name="errorEnable" value="errorEnable" />Do you want to see error response?</label></td>
314
- <td class="autoRenew"><label><input type="checkbox" name="autoRenew" value="autoRenew" />Do you want to auto-renew 1 hour</label></td>
315
297
  </tr>
316
298
  <tr>
317
299
  <td class="userState">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "0.0.29-alpha9",
3
+ "version": "0.0.29-beta2",
4
4
  "description": "Bookreader actions for borrowable book",
5
5
  "author": "Internet Archive",
6
6
  "license": "AGPL-3.0-only",
@@ -43,12 +43,6 @@
43
43
  "sinon": "^13.0.2"
44
44
  },
45
45
  "eslintConfig": {
46
- "rules": {
47
- "no-console": "off",
48
- "no-unused-expressions": "off",
49
- "class-methods-use-this": "off",
50
- "lit-a11y/click-events-have-key-events": "off"
51
- },
52
46
  "extends": [
53
47
  "@open-wc/eslint-config",
54
48
  "eslint-config-prettier"
@@ -60,6 +54,7 @@
60
54
  },
61
55
  "husky": {
62
56
  "hooks": {
57
+ "pre-commit": "lint-staged"
63
58
  }
64
59
  },
65
60
  "lint-staged": {
@@ -100,7 +100,7 @@ export const canBrowseAndBorrow = {
100
100
  // userid: "",
101
101
  bookUrl: '/details/practicalorganic00plim',
102
102
  daysLeftOnLoan: 0,
103
- isAdmin: false,
103
+ isAdmin: true,
104
104
  isArchiveOrgLending: true,
105
105
  isAvailable: false,
106
106
  isAvailableForBrowsing: false,
@@ -28,8 +28,6 @@ export class CollapsibleActionGroup extends ActionsHandler {
28
28
  dropdownArrow: { type: String },
29
29
  disabled: { type: Boolean },
30
30
  returnUrl: { type: String },
31
- localCache: { type: Function },
32
- browseAgainNow: { type: Boolean },
33
31
  };
34
32
  }
35
33
 
@@ -49,8 +47,6 @@ export class CollapsibleActionGroup extends ActionsHandler {
49
47
  this.loaderIcon = 'https://archive.org/upload/images/tree/loading.gif';
50
48
  this.disabled = false;
51
49
  this.returnUrl = '';
52
- this.localCache = undefined;
53
- this.browseAgainNow = false;
54
50
  }
55
51
 
56
52
  updated(changed) {
@@ -60,16 +56,6 @@ export class CollapsibleActionGroup extends ActionsHandler {
60
56
  ) {
61
57
  this.resetActions();
62
58
  }
63
-
64
- if (changed.has('browseAgainNow') && this.browseAgainNow === true) {
65
- this.dispatchEvent(
66
- new CustomEvent('autoBrowseBook', {
67
- detail: {
68
- event: { autoRenewed1Hour: 'browseBook' },
69
- },
70
- })
71
- );
72
- }
73
59
  }
74
60
 
75
61
  /**
@@ -161,7 +147,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
161
147
  get renderSecondaryActions() {
162
148
  if (!this.secondaryActions.length) return nothing;
163
149
 
164
- return this.secondaryActions.map(action => this.renderActionLink(action));
150
+ return this.secondaryActions.map(action => this.renderActionButton(action));
165
151
  }
166
152
 
167
153
  /**
@@ -55,7 +55,7 @@ export class InfoIcon extends LitElement {
55
55
  .more-info-icon.mobile {
56
56
  position: absolute;
57
57
  top: 4px;
58
- right: 55px;
58
+ right: 10px;
59
59
  margin-top: 15px;
60
60
  }
61
61
  .hidden {
@@ -206,8 +206,6 @@ export default class ActionsConfig {
206
206
  id: 'adminAccess',
207
207
  text: 'Admin Access',
208
208
  title: 'You have administrative privileges to read this book',
209
- url: '?admin=1',
210
- target: '_self',
211
209
  className: 'danger',
212
210
  analyticsEvent: {
213
211
  category: this.analyticsCategories.adminAccess,
@@ -17,9 +17,8 @@ export default class ActionsHandler extends LitElement {
17
17
  super();
18
18
  this.identifier = '';
19
19
  this.ajaxTimeout = 6000;
20
- this.returnUrl = '';
21
- this.autoRenewConfig = {};
22
20
  this.bindEvents();
21
+ this.returnUrl = '';
23
22
  }
24
23
 
25
24
  sendEvent(eventCategory, eventAction) {
@@ -30,7 +29,7 @@ export default class ActionsHandler extends LitElement {
30
29
  );
31
30
  }
32
31
 
33
- async bindEvents() {
32
+ bindEvents() {
34
33
  this.addEventListener('browseBook', ({ detail }) => {
35
34
  this.handleBrowseIt();
36
35
  this.setConsecutiveLoanCounts();
@@ -45,13 +44,6 @@ export default class ActionsHandler extends LitElement {
45
44
  this.sendEvent(category, action);
46
45
  });
47
46
 
48
- this.addEventListener('autoBrowseBook', ({ detail }) => {
49
- console.log('auto renew handlerExecuted!!');
50
- this.handleAutoBrowseIt();
51
- const { category, action } = detail.event;
52
- this.sendEvent(category, action);
53
- });
54
-
55
47
  this.addEventListener('returnNow', ({ detail }) => {
56
48
  this.handleReturnIt();
57
49
  const { category, action } = detail.event;
@@ -90,6 +82,11 @@ export default class ActionsHandler extends LitElement {
90
82
  this.addEventListener('adminAccess', ({ detail }) => {
91
83
  const { category, action } = detail.event;
92
84
  this.sendEvent(category, action);
85
+
86
+ // keep existing params and add new one
87
+ const url = new URL(window.location.href);
88
+ url.searchParams.append('admin', 1);
89
+ window.location.search = url.search;
93
90
  });
94
91
 
95
92
  this.addEventListener('exitAdminAccess', ({ detail }) => {
@@ -106,7 +103,6 @@ export default class ActionsHandler extends LitElement {
106
103
  handleBrowseIt() {
107
104
  const action = 'browse_book';
108
105
  this.dispatchToggleActionGroup();
109
- this.setBrowseTimeSession();
110
106
 
111
107
  ActionsHandlerService({
112
108
  action,
@@ -120,22 +116,6 @@ export default class ActionsHandler extends LitElement {
120
116
  });
121
117
  }
122
118
 
123
- handleAutoBrowseIt() {
124
- const action = 'renew_loan';
125
- this.setBrowseTimeSession();
126
-
127
- ActionsHandlerService({
128
- action,
129
- identifier: this.identifier,
130
- success: () => {
131
- // console.log('success!');
132
- },
133
- error: data => {
134
- this.dispatchActionError(action, data);
135
- },
136
- });
137
- }
138
-
139
119
  handleReturnIt() {
140
120
  const action = 'return_loan';
141
121
  this.dispatchToggleActionGroup();
@@ -286,21 +266,6 @@ export default class ActionsHandler extends LitElement {
286
266
  }
287
267
  }
288
268
 
289
- async setBrowseTimeSession() {
290
- try {
291
- // set a value
292
- await this.localCache.set({
293
- key: `${this.identifier}-loanTime`,
294
- value: new Date(), // current time
295
- ttl: Number(this.autoRenewConfig.totalTime),
296
- });
297
-
298
- await this.localCache.delete(`${this.identifier}-pageFlipTime`);
299
- } catch (error) {
300
- console.log(error);
301
- }
302
- }
303
-
304
269
  deleteLoanCookies() {
305
270
  const date = new Date();
306
271
  date.setTime(date.getTime() - 24 * 60 * 60 * 1000); // one day ago
@@ -1,21 +1,17 @@
1
1
  /* eslint-disable camelcase */
2
- import { html, css, LitElement, nothing } from 'lit';
2
+ import { html, css, LitElement } from 'lit';
3
3
 
4
4
  import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
5
5
  import { ModalConfig } from '@internetarchive/modal-manager';
6
- import { LocalCache } from '@internetarchive/local-cache';
7
6
 
8
7
  import './components/collapsible-action-group.js';
9
8
  import './components/book-title-bar.js';
10
9
  import './components/text-group.js';
11
10
  import './components/info-icon.js';
12
- import './components/timer-countdown.js';
13
- import './components/toast-message.js';
14
11
 
15
12
  import { GetLendingActions } from './core/services/get-lending-actions.js';
16
13
  import { mobileContainerWidth } from './core/config/constants.js';
17
14
  import { LoanTokenPoller } from './core/services/loan-token-poller.js';
18
- import { OneHourAutoRenew } from './core/services/one-hour-auto-renew.js';
19
15
 
20
16
  export const events = {
21
17
  browseExpired: 'IABookReader:BrowsingHasExpired',
@@ -40,12 +36,6 @@ export default class IABookActions extends LitElement {
40
36
  disableActionGroup: { type: Boolean },
41
37
  modal: { Object },
42
38
  tokenDelay: { type: Number },
43
- toastTexts: { type: String },
44
- remainingTime: { type: Number },
45
- resetTimerCountdown: { type: Boolean },
46
- localCache: { type: Object },
47
- autoRenewConfig: { type: Object },
48
- browseAgainNow: { type: Boolean },
49
39
  };
50
40
  }
51
41
 
@@ -64,11 +54,6 @@ export default class IABookActions extends LitElement {
64
54
  this.disableActionGroup = false;
65
55
  this.modal = undefined;
66
56
  this.tokenDelay = 120000; // 2 minutes
67
- this.localCache = new LocalCache({
68
- namespace: '1HourLoanStorage',
69
- });
70
- this.autoRenewConfig = {};
71
- this.autoRenewRes = undefined;
72
57
 
73
58
  // private props
74
59
  this.primaryActions = [];
@@ -78,12 +63,6 @@ export default class IABookActions extends LitElement {
78
63
  this.lendingOptions = {};
79
64
  this.borrowType = ''; // (browsed|borrowed)
80
65
  this.consecutiveLoanCounts = 1; // consecutive loan count
81
- this.browseAgainNow = false;
82
- this.browserTimer = undefined;
83
- this.hideToast = true;
84
-
85
- this.bindAutoRenewEvent();
86
- this.resetTimerCountdown = false;
87
66
  }
88
67
 
89
68
  disconnectedCallback() {
@@ -100,7 +79,6 @@ export default class IABookActions extends LitElement {
100
79
  }
101
80
 
102
81
  updated(changed) {
103
- // console.log(changed)
104
82
  if (changed.has('lendingStatus') || changed.has('bwbPurchaseUrl')) {
105
83
  this.setupLendingToolbarActions();
106
84
  this.update();
@@ -112,74 +90,12 @@ export default class IABookActions extends LitElement {
112
90
  }
113
91
  }
114
92
 
115
- bindAutoRenewEvent() {
116
- // dispatched this event from timer-countdown
117
- this.addEventListener('autoRenewAttempt', async event => {
118
- const isPageClick = event.detail.bookPageChange;
119
-
120
- // early return if user is not browsed book
121
- if (isPageClick && this.borrowType !== 'browsed') return nothing;
122
-
123
- this.autoRenewRes = await new OneHourAutoRenew(
124
- isPageClick,
125
- this.identifier,
126
- this.localCache,
127
- this.autoRenewConfig,
128
- this.lendingStatus.user_has_browsed &&
129
- !this.lendingStatus.browsingExpired
130
- );
131
- console.log(this.autoRenewRes);
132
-
133
- this.toastTexts = this.autoRenewRes.toastTexts;
134
- this.hideToast = this.autoRenewRes.hideToast;
135
- this.browseAgainNow = this.autoRenewRes.browseAgainNow;
136
-
137
- if (this.browseAgainNow) {
138
- this.tokenPoller.disconnectedInterval();
139
-
140
- // start tokenPoller after 2 minute
141
- setTimeout(() => {
142
- this.startLoanTokenPoller();
143
- }, this.tokenDelay);
144
-
145
- await this.browseHasRenew();
146
- }
147
-
148
- return nothing;
149
- });
150
- }
151
-
152
- async browseHasExpired() {
93
+ browseHasExpired() {
153
94
  const currStatus = { ...this.lendingStatus, browsingExpired: true };
154
95
  this.lendingStatus = currStatus;
155
- this.browseAgainNow = false;
156
-
157
- // remove respected key:value
158
- await this.localCache.delete(`${this.identifier}-loanTime`);
159
- await this.localCache.delete(`${this.identifier}-pageFlipTime`);
160
-
161
- // show message after browsed book is expired.
162
- this.toastTexts = 'This book has been auto-returned due to inactivity.';
163
- }
164
-
165
- async browseHasRenew() {
166
- const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
167
- const secondsLeft = (loanTime - new Date()) / 1000; // different in seconds
168
-
169
- const currStatus = {
170
- ...this.lendingStatus,
171
- user_has_browsed: true,
172
- browsingExpired: false,
173
- secondsLeftOnLoan: secondsLeft,
174
- };
175
- this.lendingStatus = currStatus;
176
-
177
- this.startBrowseTimer();
178
96
  }
179
97
 
180
98
  startBrowseTimer() {
181
- clearTimeout(this.browserTimer);
182
-
183
99
  const {
184
100
  browsingExpired,
185
101
  user_has_browsed,
@@ -189,9 +105,8 @@ export default class IABookActions extends LitElement {
189
105
  return;
190
106
  }
191
107
 
192
- // expired book and show browse again button
193
108
  const timeLeft = secondsLeftOnLoan * 1000;
194
- this.browserTimer = setTimeout(() => {
109
+ setTimeout(() => {
195
110
  this.browseHasExpired();
196
111
  }, timeLeft);
197
112
  }
@@ -249,13 +164,16 @@ export default class IABookActions extends LitElement {
249
164
  });
250
165
 
251
166
  this.borrowType = actions.borrowType;
252
- this.remainingTime = this.lendingStatus.secondsLeftOnLoan;
253
167
 
254
168
  const hasExpired =
255
169
  'browsingExpired' in this.lendingStatus &&
256
170
  this.lendingStatus?.browsingExpired;
257
171
  if (hasExpired) {
258
- window?.Sentry?.captureMessage('setupLendingToolbarActions hasExpired');
172
+ if (!this.tokenPoller.disconnectedInterval) {
173
+ window?.Sentry?.captureMessage(
174
+ 'setupLendingToolbarActions hasExpired - no tokenPoller'
175
+ );
176
+ }
259
177
  this.tokenPoller?.disconnectedInterval();
260
178
  /** Global event - always fire */
261
179
  this.dispatchEvent(
@@ -302,30 +220,8 @@ export default class IABookActions extends LitElement {
302
220
  ></book-title-bar>`;
303
221
  }
304
222
 
305
- get timerCountdownTemplate() {
306
- // console.log(this.borrowType, this.remainingTime, this.autoRenewConfig.autoCheckAt, this.resetTimerCountdown);
307
- return this.borrowType === 'browsed'
308
- ? html`<timer-countdown
309
- time=${Number(this.remainingTime)}
310
- .autoCheckAt=${this.autoRenewConfig.autoCheckAt}
311
- ?resetTimerCountdown=${this.resetTimerCountdown}
312
- ></timer-countdown>`
313
- : nothing;
314
- }
315
-
316
- get toastMessageTemplate() {
317
- return html`
318
- <toast-message
319
- .texts=${this.toastTexts}
320
- ?dismisOnClick=${Boolean(true)}
321
- ?hideToast=${this.hideToast}
322
- ></toast-message>
323
- `;
324
- }
325
-
326
223
  get bookActionBar() {
327
224
  return html`
328
- <button @click=${() => this.pageFlipEvent()}>Page Flip</button>
329
225
  <collapsible-action-group
330
226
  .userid=${this.userid}
331
227
  .identifier=${this.identifier}
@@ -335,30 +231,16 @@ export default class IABookActions extends LitElement {
335
231
  .width=${this.width}
336
232
  .borrowType=${this.borrowType}
337
233
  .returnUrl=${this.returnUrl}
338
- .localCache=${this.localCache}
339
- .autoRenewConfig=${this.autoRenewConfig}
340
234
  ?hasAdminAccess=${this.hasAdminAccess}
341
235
  ?disabled=${this.disableActionGroup}
342
- ?browseAgainNow=${this.browseAgainNow}
343
236
  @lendingActionError=${this.handleLendingActionError}
344
237
  @toggleActionGroup=${this.handleToggleActionGroup}
345
238
  >
346
239
  </collapsible-action-group>
347
240
  ${this.textGroupTemplate} ${this.infoIconTemplate}
348
- ${this.timerCountdownTemplate} ${this.toastMessageTemplate}
349
241
  `;
350
242
  }
351
243
 
352
- // will move this function to bookreader...
353
- pageFlipEvent() {
354
- // dispatch event to say book page has flipped
355
- document.querySelector('ia-book-actions').dispatchEvent(
356
- new CustomEvent('autoRenewAttempt', {
357
- detail: { bookPageChange: true },
358
- })
359
- );
360
- }
361
-
362
244
  /**
363
245
  * enable access of borrowed/browsed books
364
246
  */
@@ -523,10 +405,6 @@ export default class IABookActions extends LitElement {
523
405
  justify-content: center;
524
406
  flex-wrap: wrap;
525
407
  }
526
-
527
- toast-message {
528
- --messageHeightFromTop: 17%;
529
- }
530
408
  `;
531
409
  }
532
410
  }
@@ -1,113 +0,0 @@
1
- import { html, css, LitElement } from 'lit';
2
-
3
- export default class TimerCountdown extends LitElement {
4
- static get properties() {
5
- return {
6
- time: { type: Number },
7
- autoCheckAt: { type: Number },
8
- resetTimerCountdown: { type: Boolean },
9
- };
10
- }
11
-
12
- constructor() {
13
- super();
14
- this.time = 0;
15
- this.autoCheckAt = 0;
16
- this.timerInterval = undefined;
17
- this.resetTimerCountdown = false;
18
- }
19
-
20
- disconnectedCallback() {
21
- clearInterval(this.timerInterval);
22
- }
23
-
24
- updated(changed) {
25
- if (changed.has('time') && this.time > 0) {
26
- clearInterval(this.timerInterval);
27
- this.timerCountdown();
28
- }
29
- }
30
-
31
- timerCountdown() {
32
- this.timerInterval = setInterval(() => {
33
- this.time -= 1;
34
-
35
- // execute 50th minute check
36
- if (Math.round(this.time) === this.autoCheckAt) {
37
- this.dispatchEvent(
38
- new CustomEvent('autoRenewAttempt', {
39
- detail: {
40
- remainingT: this.time,
41
- bookPageChange: false,
42
- },
43
- bubbles: true,
44
- composed: true,
45
- })
46
- );
47
- }
48
-
49
- if (this.time === 0) clearInterval(this.timerInterval);
50
- }, 1000);
51
- }
52
-
53
- render() {
54
- return html`<div id="countdown">
55
- <div id="countdown-number">${Math.round(this.time)}</div>
56
- <svg>
57
- <circle r="18" cx="20" cy="20"></circle>
58
- </svg>
59
- </div>`;
60
- }
61
-
62
- static get styles() {
63
- return css`
64
- :host {
65
- right: 5px;
66
- font-size: 14px;
67
- position: absolute;
68
- }
69
- #countdown-number {
70
- color: white;
71
- display: inline-block;
72
- line-height: 40px;
73
- margin-right: 12px;
74
- }
75
-
76
- svg {
77
- position: absolute;
78
- top: 0;
79
- right: 0;
80
- width: 40px;
81
- height: 40px;
82
- transform: rotateY(-180deg) rotateZ(-90deg);
83
- }
84
-
85
- svg circle {
86
- stroke-dasharray: 113px;
87
- stroke-dashoffset: 0px;
88
- stroke-linecap: round;
89
- stroke-width: 3px;
90
- stroke: white;
91
- fill: none;
92
- animation: countdown 60s linear infinite forwards;
93
- }
94
-
95
- @keyframes countdown {
96
- from {
97
- stroke-dashoffset: 0px;
98
- }
99
- to {
100
- stroke-dashoffset: 113px;
101
- }
102
- }
103
- .hidden {
104
- display: none;
105
- }
106
- .visible {
107
- display: inline-block;
108
- }
109
- `;
110
- }
111
- }
112
-
113
- window.customElements.define('timer-countdown', TimerCountdown);
@@ -1,78 +0,0 @@
1
- import { html, css, LitElement, nothing } from 'lit';
2
-
3
- export class ToastMessage extends LitElement {
4
- static get properties() {
5
- return {
6
- texts: { type: String },
7
- dismisOnClick: { type: Boolean },
8
- hideToast: { type: Boolean },
9
- };
10
- }
11
-
12
- constructor() {
13
- super();
14
- this.texts = '';
15
- this.textClass = '';
16
- this.hideToast = false;
17
- }
18
-
19
- render() {
20
- return !this.hideToast
21
- ? html`
22
- <span
23
- class="toast-message fade-in ${this.textClass}"
24
- title="Click/tap to close"
25
- @click=${() => {
26
- this.dismisOnClick ? (this.hideToast = true) : nothing;
27
- }}
28
- >${this.texts}</span
29
- >
30
- `
31
- : nothing;
32
- }
33
-
34
- static get styles() {
35
- const heightFromTop = css`var(--messageHeightFromTop, 15%)`;
36
-
37
- return css`
38
- :host {
39
- display: inline-block;
40
- }
41
- .toast-message {
42
- z-index: 2;
43
- position: absolute;
44
- top: ${heightFromTop};
45
- font-size: 1.4rem;
46
- font-family: 'Helvetica Neue';
47
- color: #fff;
48
- left: 50%;
49
- background: #333;
50
- border: 1px solid #fff;
51
- border-radius: 5px;
52
- box-shadow: 1px 1px 2px;
53
- padding: 10px;
54
- width: fit-content;
55
- transform: translate(-50%, -50%);
56
- cursor: pointer;
57
- animation: fadeIn 5s;
58
- @keyframes fadeIn {
59
- 0% {
60
- opacity: 0;
61
- }
62
- 100% {
63
- opacity: 1;
64
- }
65
- }
66
- }
67
-
68
- .hidden {
69
- display: none;
70
- }
71
- .visible {
72
- display: inline-block;
73
- }
74
- `;
75
- }
76
- }
77
-
78
- window.customElements.define('toast-message', ToastMessage);
@@ -1,169 +0,0 @@
1
- import { nothing } from 'lit';
2
-
3
- /**
4
- * This class is used to determine if use is eligible for auto renew loan.
5
- *
6
- */
7
- export class OneHourAutoRenew {
8
- constructor(
9
- isPageClick,
10
- identifier,
11
- localCache,
12
- autoRenewConfig,
13
- userHasBrowsed
14
- ) {
15
- this.isPageClick = isPageClick;
16
- this.identifier = identifier;
17
- this.localCache = localCache;
18
- this.autoRenewConfig = autoRenewConfig;
19
- this.userHasBrowsed = userHasBrowsed;
20
-
21
- // messages for auto return machenism
22
- this.autoRenewMessage = 'This book has been renewed for another hour.';
23
- this.autoReturnMessage =
24
- 'This book has been auto-returned due to inactivity.';
25
- this.autoReturnWarning =
26
- 'This book will be auto-returned in 10 minutes unless you turn a page.';
27
-
28
- // private props
29
- this.resultRes = {
30
- toastTexts: '',
31
- hideToast: true,
32
- renewNow: false,
33
- browseAgainNow: false,
34
- };
35
-
36
- return this.handleBookAutoRenew();
37
- }
38
-
39
- handleBookAutoRenew() {
40
- try {
41
- // if page is not clicked in last 15 minutes,
42
- // instantaly renew it if user viewed new page in last 10 minutes
43
- if (this.isPageClick) {
44
- console.log('page flipped!!');
45
- return this.userFlippedBookPage(); // user clicked on page
46
- }
47
- console.log('auto checker!');
48
- return this.autoCheckerTimer(); // auto checker at 50th minute
49
- } catch (error) {
50
- console.log(error);
51
- }
52
-
53
- return nothing;
54
- }
55
-
56
- async setPageFlippedTime() {
57
- // set pageFlipTime time in localStorage
58
- await this.localCache.set({
59
- key: `${this.identifier}-pageFlipTime`,
60
- value: new Date(), // current time
61
- ttl: Number(this.autoRenewConfig.totalTime),
62
- });
63
- }
64
-
65
- async userFlippedBookPage() {
66
- const {
67
- totalTime, // 60
68
- autoCheckAt, // 50
69
- } = this.autoRenewConfig;
70
- const currentTime = new Date();
71
- const loanTime = await this.localCache.get(`${this.identifier}-loanTime`);
72
-
73
- const lastTimeFrame = this.changeTime(
74
- loanTime,
75
- totalTime - autoCheckAt,
76
- 'add'
77
- ); // 50 seconds
78
-
79
- if (currentTime >= lastTimeFrame) {
80
- console.log('1 YES NOW BORROW IT AGAIN NOW!');
81
- this.resultRes.toastTexts = this.autoRenewMessage;
82
- this.resultRes.hideToast = false;
83
- this.resultRes.renewNow = true;
84
- this.resultRes.browseAgainNow = true;
85
-
86
- this.setNewBrowseTime();
87
- }
88
-
89
- this.setPageFlippedTime();
90
- return this.resultRes;
91
- }
92
-
93
- async autoCheckerTimer() {
94
- const currentTime = new Date();
95
- const { FlippedInLast } = this.autoRenewConfig;
96
- const lastPageFlipTime = await this.localCache.get(
97
- `${this.identifier}-pageFlipTime`
98
- );
99
-
100
- // last 15 min if used flipped a page.
101
- const lastFlipTimeFrame = this.changeTime(
102
- currentTime,
103
- FlippedInLast,
104
- 'sub'
105
- ); // 15 seconds
106
-
107
- if (
108
- lastPageFlipTime === undefined ||
109
- lastPageFlipTime <= lastFlipTimeFrame
110
- ) {
111
- // not viewed
112
- console.log('2 not viewed, warning message!');
113
- this.resultRes.toastTexts = this.autoReturnWarning;
114
- this.resultRes.hideToast = false;
115
- } else if (lastPageFlipTime >= lastFlipTimeFrame) {
116
- // viewed in last time frame
117
- console.log('3 viewed, auto renew and message!');
118
- this.resultRes.toastTexts = this.autoRenewMessage;
119
- this.resultRes.browseAgainNow = true;
120
- this.resultRes.hideToast = false;
121
- this.resultRes.renewNow = true;
122
-
123
- this.setNewBrowseTime();
124
- }
125
-
126
- return this.resultRes;
127
- }
128
-
129
- async setNewBrowseTime() {
130
- try {
131
- // last 15 min if used flipped a page.
132
- const expireDate = this.changeTime(
133
- new Date(),
134
- this.autoRenewConfig.totalTime,
135
- 'add'
136
- ); // 15 seconds
137
-
138
- // set a value
139
- await this.localCache.set({
140
- key: `${this.identifier}-loanTime`,
141
- value: expireDate, // expireDate time
142
- ttl: Number(this.autoRenewConfig.totalTime),
143
- });
144
-
145
- // delete pageFlipTime when book is auto renew at nth minute
146
- await this.localCache.delete(`${this.identifier}-pageFlipTime`);
147
- } catch (error) {
148
- console.log(error);
149
- }
150
- }
151
-
152
- changeTime(date, minutes, op) {
153
- if (date === undefined) return nothing;
154
-
155
- if (op === 'sub') {
156
- return new Date(date.getTime() - minutes * 1000);
157
- }
158
-
159
- return new Date(date.getTime() + minutes * 1000);
160
- }
161
-
162
- sendEvent(eventCategory, eventAction) {
163
- window?.archive_analytics?.send_event(
164
- eventCategory,
165
- eventAction,
166
- `identifier=${this.identifier}`
167
- );
168
- }
169
- }