@internetarchive/ia-book-actions 1.4.2 → 1.4.3-alpha1

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/index.html CHANGED
@@ -38,11 +38,13 @@
38
38
 
39
39
  fieldset {
40
40
  width: fit-content;
41
+ max-width: 100%;
42
+ box-sizing: border-box;
41
43
  margin-top: 50px;
42
44
  }
43
45
  fieldset legend {
44
46
  text-align: left;
45
- font-size: 12px;
47
+ font-size: 14px;
46
48
  }
47
49
  td {
48
50
  color: white;
@@ -52,7 +54,7 @@
52
54
  text-align: initial;
53
55
  margin: 5px 0;
54
56
  width: max-content;
55
- display: block;
57
+ display: inline;
56
58
  }
57
59
  label {
58
60
  padding: 10px;
@@ -83,9 +85,103 @@
83
85
  border-radius: 10px;
84
86
  }
85
87
 
88
+ .timer-presets {
89
+ display: flex;
90
+ gap: 6px;
91
+ flex-wrap: wrap;
92
+ max-width: 100%;
93
+ }
94
+ .timer-presets button {
95
+ padding: 6px 10px;
96
+ cursor: pointer;
97
+ border: 2px solid #194880;
98
+ border-radius: 10px;
99
+ background: white;
100
+ }
101
+ .timer-presets button.active-preset {
102
+ background: #194880;
103
+ color: white;
104
+ }
105
+
106
+ #live-status-wrapper {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: 10px;
110
+ flex-wrap: wrap;
111
+ /* width: min(400px, 100%); */
112
+
113
+ /* display: flex; gap: 3rem; margin: 0 3rem; flex-wrap: wrap; */
114
+ }
115
+ #loan-status-row,
116
+ #lending-bar-controls {
117
+ display: grid;
118
+ grid-template-columns: repeat(2, 1fr);
119
+ gap: 3rem;
120
+ margin: 0 3rem;
121
+ }
122
+ @media (max-width: 700px) {
123
+ #loan-status-row,
124
+ #lending-bar-controls {
125
+ grid-template-columns: 1fr;
126
+ }
127
+ }
128
+ .loan-status-badge {
129
+ display: inline-block;
130
+ padding: 8px 14px;
131
+ border-radius: 6px;
132
+ font-size: 14px;
133
+ font-weight: bold;
134
+ letter-spacing: 0.5px;
135
+ color: white;
136
+ }
137
+ .loan-status-badge.status-active {
138
+ background: #2e7d32; /* green: loan is currently checked out */
139
+ }
140
+ .loan-status-badge.status-returned {
141
+ background: #d9534f; /* red: auto-returned / not on loan */
142
+ }
143
+ .loan-status-badge.status-none {
144
+ background: #666; /* gray: nothing borrowed yet */
145
+ }
146
+ #live-status-detail {
147
+ color: white;
148
+ background: #333;
149
+ padding: 8px 12px;
150
+ border-radius: 6px;
151
+ font-size: 12px;
152
+ text-align: left;
153
+ flex: 1;
154
+ }
155
+ #exec-log {
156
+ text-align: left;
157
+ background: #111;
158
+ color: #9fef9f;
159
+ font-family: monospace;
160
+ font-size: 11px;
161
+ max-height: 160px;
162
+ overflow-y: auto;
163
+ padding: 8px;
164
+ border-radius: 6px;
165
+ margin-top: 8px;
166
+ white-space: pre-wrap;
167
+ word-break: break-word;
168
+ }
169
+ #exec-log div + div {
170
+ border-top: 1px solid #333;
171
+ padding-top: 2px;
172
+ margin-top: 2px;
173
+ }
174
+
175
+ #auto-renew-controls {
176
+ display: none1;
177
+ }
86
178
  body.modal-manager-open {
87
179
  overflow: hidden;
88
180
  }
181
+
182
+ #action-bar-modal {
183
+ --modalWidth: 35rem;
184
+ }
89
185
 
90
186
  modal-manager[mode='closed'] {
91
187
  display: none;
@@ -96,6 +192,44 @@
96
192
  <body>
97
193
  <ia-book-actions></ia-book-actions>
98
194
 
195
+ <script>
196
+ /* eslint-disable */
197
+ // WEBDEV-8322: capture the library's `log()` lines — API calls
198
+ // (create_token/browse_book/borrow_book/renew_loan/return_loan and their
199
+ // success/error from ActionsHandlerService), lifecycle events
200
+ // ([IABookActions]: page-turn/BookReader:userAction received,
201
+ // visibilitychange backgrounded/foregrounded, browseHasExpired,
202
+ // showWarningModal, handleLoanAutoRenewed, etc), and anything the demo
203
+ // itself triggers ([Demo]: user_has_browsed set, error-mode toggled,
204
+ // etc) — into the live status panel below, so QA can see everything
205
+ // that happened without opening devtools. GA event-mirroring noise
206
+ // (`eventCategory:- ...`) is the one thing still filtered out.
207
+ //
208
+ // This MUST run as a plain (non-module) script BEFORE the `type="module"`
209
+ // script's imports execute: `log.js` binds its own reference to
210
+ // `console.log` the moment it's imported, so overriding console.log any
211
+ // later (even earlier in the module script's own source) would miss it —
212
+ // ES module imports always run before the importing module's own
213
+ // top-level code, regardless of source order.
214
+ window.__execLog = [];
215
+ const __nativeConsoleLog = console.log.bind(console);
216
+ console.log = (...consoleArgs) => {
217
+ __nativeConsoleLog(...consoleArgs);
218
+
219
+ const loggedPrefixes = ['[ActionsHandlerService]', '[IABookActions]', '[Demo]'];
220
+ if (typeof consoleArgs[0] !== 'string' || !loggedPrefixes.some((prefix) => consoleArgs[0].startsWith(prefix))) {
221
+ return;
222
+ }
223
+
224
+ const time = new Date().toISOString().split('T')[1].replace('Z', '');
225
+ const text = `[${time}] ` + consoleArgs
226
+ .map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg)))
227
+ .join(' ');
228
+ window.__execLog.push(text);
229
+ if (window.__renderExecLogEntry) window.__renderExecLogEntry(text);
230
+ };
231
+ </script>
232
+
99
233
  <script type="module">
100
234
  /* eslint-disable */
101
235
 
@@ -139,31 +273,32 @@
139
273
  iaBookActions.returnUrl = '';
140
274
  iaBookActions.localCache = localCache;
141
275
 
142
- let loanTotalTime2Min = { loanTotalTime: 120, loanRenewAtLast: 110, pageChangedInLast: 30 };
143
- let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 240, pageChangedInLast: 60 };
144
- let loanTotalTime10Min = { loanTotalTime: 600, loanRenewAtLast: 480, pageChangedInLast: 120 };
145
- let loanTotalTime30Min = { loanTotalTime: 1800, loanRenewAtLast: 1500, pageChangedInLast: 600 };
146
- let loanTotalTime1Hour = { loanTotalTime: 3600, loanRenewAtLast: 660, pageChangedInLast: 900 };
276
+ // Loan-duration presets for QA — pick a short one (15s/30s) to run through
277
+ // the full warn -> auto-return -> silent-reborrow lifecycle quickly, or a
278
+ // longer one (60min matches the real 1-hour production default) to check
279
+ // the timing math. `?timer=` accepts any key below (e.g. ?timer=15s).
280
+ const timerPresets = {
281
+ '15s': { loanTotalTime: 15, loanRenewAtLast: 13, pageChangedInLast: 5 },
282
+ '30s': { loanTotalTime: 30, loanRenewAtLast: 27, pageChangedInLast: 10 },
283
+ '2': { loanTotalTime: 120, loanRenewAtLast: 110, pageChangedInLast: 30 },
284
+ '5': { loanTotalTime: 300, loanRenewAtLast: 240, pageChangedInLast: 60 },
285
+ '10': { loanTotalTime: 600, loanRenewAtLast: 480, pageChangedInLast: 120 },
286
+ '30': { loanTotalTime: 1800, loanRenewAtLast: 1500, pageChangedInLast: 600 },
287
+ '60': { loanTotalTime: 3600, loanRenewAtLast: 660, pageChangedInLast: 900 }, // production default
288
+ };
147
289
 
148
- iaBookActions.loanRenewTimeConfig = loanTotalTime2Min;
149
290
  let params = new URLSearchParams(document.location.search);
150
- switch (params.get("timer")) {
151
- case '5':
152
- iaBookActions.loanRenewTimeConfig = loanTotalTime5Min;
153
- break;
154
- case '10':
155
- iaBookActions.loanRenewTimeConfig = loanTotalTime10Min;
156
- break;
157
- case '30':
158
- iaBookActions.loanRenewTimeConfig = loanTotalTime30Min;
159
- break;
160
- case '60':
161
- iaBookActions.loanRenewTimeConfig = loanTotalTime1Hour;
162
- break;
163
- default:
164
- iaBookActions.loanRenewTimeConfig = loanTotalTime2Min;
165
- break;
166
- }
291
+ const activeTimerKey = timerPresets[params.get('timer')] ? params.get('timer') : '2';
292
+ iaBookActions.loanRenewTimeConfig = timerPresets[activeTimerKey];
293
+
294
+ document.querySelectorAll('.timer-presets button').forEach((button) => {
295
+ if (button.dataset.timer === activeTimerKey) button.classList.add('active-preset');
296
+ button.addEventListener('click', () => {
297
+ const searchParams = new URLSearchParams(window.location.search);
298
+ searchParams.set('timer', button.dataset.timer);
299
+ window.location.search = searchParams.toString();
300
+ });
301
+ });
167
302
 
168
303
  let lendingStatus1 = iaBookActions.lendingStatus;
169
304
  let secondsLeftOnLoan = iaBookActions.loanRenewTimeConfig.loanTotalTime;
@@ -202,6 +337,8 @@
202
337
  item.checked = true;
203
338
  }
204
339
  item.addEventListener('click', (e) => {
340
+ console.log(`[Demo] error-response mode ${e.target.checked ? 'enabled' : 'disabled'}`);
341
+
205
342
  var searchParams = new URLSearchParams(window.location.search);
206
343
  var separate = '';
207
344
  if (e.target.checked) {
@@ -251,6 +388,8 @@
251
388
 
252
389
  document.querySelectorAll('.availableToBrowse input[type=radio]').forEach((item) => {
253
390
  item.addEventListener('click', async (e) => {
391
+ console.log(`[Demo] "${e.target.value}" selected under availableToBrowse`);
392
+
254
393
  if (e.target.value === 'user_has_browsed') {
255
394
  lendingStatus1.user_has_browsed = true;
256
395
  lendingStatus1.available_to_browse = false;
@@ -289,7 +428,11 @@
289
428
  });
290
429
  });
291
430
 
431
+ // WEBDEV-8322 scenario 1: informational-only warning modal.
432
+ // "Okay" (or closing it) must NOT renew the loan — only interacting
433
+ // with the book (scenario 3 below) does that.
292
434
  document.querySelector('#show_warning_modal').addEventListener('click', async () => {
435
+ console.log('[Demo] scenario 1 button clicked: show warning modal');
293
436
  if (!iaBookActions.lendingStatus.user_has_browsed) {
294
437
  const newLendingStatus = { ...iaBookActions.lendingStatus, user_has_browsed: true };
295
438
  iaBookActions.lendingStatus = newLendingStatus;
@@ -297,24 +440,28 @@
297
440
  }
298
441
 
299
442
  iaBookActions.showWarningModal();
300
-
301
- if (iaBookActions.lendingStatus.user_has_browsed) {
302
- iaBookActions.showWarningModal();
303
- }
304
443
  });
305
444
 
445
+ // WEBDEV-8322 scenario 2: loan auto-returned due to inactivity.
446
+ // No modal should appear and the page should NOT refresh — the reader
447
+ // just silently sits on whatever page it was on.
306
448
  document.querySelector('#show_expired_modal').addEventListener('click', async () => {
449
+ console.log('[Demo] scenario 2 button clicked: force auto-return');
307
450
  if (!iaBookActions.lendingStatus.user_has_browsed) {
308
451
  const newLendingStatus = { ...iaBookActions.lendingStatus, user_has_browsed: true };
309
452
  iaBookActions.lendingStatus = newLendingStatus;
310
453
  await iaBookActions.updateComplete;
311
454
  }
312
- await new Promise(resolve => setTimeout(resolve, 5000));
455
+ await new Promise(resolve => setTimeout(resolve, 100));
313
456
 
314
457
  iaBookActions.browseHasExpired();
315
458
  });
316
459
 
460
+ // WEBDEV-8322 scenario 4: patron returns to the tab after time away.
461
+ // If the loan already expired while hidden, this silently attempts to
462
+ // re-borrow (same success/failure paths as scenario 3).
317
463
  document.querySelector('#resync_timer').addEventListener('click', async (e) => {
464
+ console.log('[Demo] scenario 4 button clicked: simulate visibilitychange (tab return)');
318
465
  if (iaBookActions.lendingStatus.user_has_browsed) {
319
466
  document.querySelector('ia-book-actions').dispatchEvent(
320
467
  new Event('visibilitychange', {
@@ -324,7 +471,7 @@
324
471
  })
325
472
  );
326
473
  }
327
- await new Promise(resolve => setTimeout(resolve, 5000));
474
+ await new Promise(resolve => setTimeout(resolve, 1000));
328
475
  });
329
476
 
330
477
  document.querySelectorAll('.availableToBorrow input[type=radio]').forEach((item) => {
@@ -373,101 +520,233 @@
373
520
  })
374
521
  });
375
522
 
376
- document.querySelector('.pageChangedEvent').addEventListener('click', () => {
377
- // dispatch event to say book page has flipped
378
- document.querySelector('ia-book-actions').dispatchEvent(
379
- new CustomEvent('BookReader:userAction', {
380
- detail: {},
381
- bubbles: true,
382
- composed: true,
383
- })
384
- );
385
- })
523
+ // WEBDEV-8322 scenario 3: patron interacts with the book (turns a page,
524
+ // etc). If the loan already expired (run scenario 2 first), this
525
+ // silently retries the loan — enable the error checkbox above beforehand
526
+ // to simulate someone else having already borrowed the book, which
527
+ // should surface the "Due to inactivity..." modal instead.
528
+ document.querySelectorAll('.pageChangedEvent').forEach((button) => {
529
+ button.addEventListener('click', () => {
530
+ console.log('[Demo] page-change / BookReader:userAction dispatched');
531
+ document.querySelector('ia-book-actions').dispatchEvent(
532
+ new CustomEvent('BookReader:userAction', {
533
+ detail: {},
534
+ bubbles: true,
535
+ composed: true,
536
+ })
537
+ );
538
+ });
539
+ });
386
540
 
387
541
  // listen for IABookReader:BrowsingHasExpired
388
542
  window.addEventListener('IABookReader:BrowsingHasExpired', () => {
389
543
  console.log('IABookReader:BrowsingHasExpired EVENT FIRED');
390
544
  });
545
+
546
+ // WEBDEV-8322 live status panel — the action bar alone doesn't always
547
+ // visibly change (e.g. right after auto-return), so mirror what the
548
+ // library's own log() calls already say is happening (create_token,
549
+ // renew_loan, browse_book, return_loan, and their success/error — see
550
+ // ActionsHandlerService) into an on-page log QA can read without
551
+ // opening devtools. The console.log interception itself lives in the
552
+ // plain <script> above this module script — see the comment there for
553
+ // why it can't live here.
554
+ const execLogEl = document.querySelector('#exec-log');
555
+ const loanStatusBadgeEl = document.querySelector('#loan-status-badge');
556
+ const liveStatusDetailEl = document.querySelector('#live-status-detail');
557
+
558
+ function renderExecLogEntry(text) {
559
+ const line = document.createElement('div');
560
+ line.textContent = text;
561
+ execLogEl.appendChild(line);
562
+ execLogEl.scrollTop = execLogEl.scrollHeight;
563
+ }
564
+ window.__renderExecLogEntry = renderExecLogEntry;
565
+ // flush anything logged before this module script finished loading
566
+ window.__execLog.forEach(renderExecLogEntry);
567
+
568
+ document.querySelector('#clear-exec-log').addEventListener('click', () => {
569
+ execLogEl.textContent = '';
570
+ window.__execLog = [];
571
+ });
572
+
573
+ // The loan-status badge answers one question only: is the loan ACTIVE
574
+ // or has it been RETURNED? `browsingExpired` is the exact flag the
575
+ // library flips the instant auto-return executes (browseHasExpired()),
576
+ // so the badge changes in the same tick — even though the action bar
577
+ // itself doesn't show a modal or refresh at that moment.
578
+ function computeLoanStatus() {
579
+ const lendingStatus = iaBookActions.lendingStatus || {};
580
+
581
+ if (lendingStatus.browsingExpired) {
582
+ return { badge: 'RETURNED', className: 'status-returned' };
583
+ }
584
+ if (lendingStatus.user_has_browsed) {
585
+ return { badge: 'ACTIVE', className: 'status-active' };
586
+ }
587
+ return { badge: 'NO LOAN', className: 'status-none' };
588
+ }
589
+
590
+ function computeLiveStatusDetail() {
591
+ const lendingStatus = iaBookActions.lendingStatus || {};
592
+
593
+ if (iaBookActions.loanRenewInProgress) {
594
+ return '🔄 Attempting silent re-borrow (create_token → renew_loan)…';
595
+ }
596
+ if (iaBookActions.warningModalOpen) {
597
+ return '⚠️ Warning modal open — closing it will NOT renew the loan';
598
+ }
599
+ if (lendingStatus.browsingExpired) {
600
+ return 'Auto-returned due to inactivity. By design: no modal, no refresh — only this badge and the action bar (Borrow) reflect it, until the patron interacts again.';
601
+ }
602
+ if (lendingStatus.user_has_browsed) {
603
+ const secondsLeft = Math.round(Number(lendingStatus.secondsLeftOnLoan || 0));
604
+ return `~${secondsLeft}s left on this loan`;
605
+ }
606
+ return 'Not currently browsing this book';
607
+ }
608
+
609
+ setInterval(() => {
610
+ const { badge, className } = computeLoanStatus();
611
+ loanStatusBadgeEl.textContent = badge;
612
+ loanStatusBadgeEl.className = `loan-status-badge ${className}`;
613
+ liveStatusDetailEl.textContent = computeLiveStatusDetail();
614
+ }, 250);
391
615
  </script>
392
616
 
393
617
  <div>
394
- <fieldset>
395
- <legend>Dev testing for book title bar</legend>
396
- <table class="initial">
397
- <tr>
398
- <td class="titleBar">
399
- <label><input type="checkbox" name="title" value="title" />Title Bar</label>
400
- </td>
401
- <td class="searchParam">
402
- <label><input type="checkbox" name="search" value="Search Param" />Search Param</label>
403
- </td>
404
- <td>
405
- <label class="ia-button"><button class="pageChangedEvent">Page Change Event</button></label>
406
- </td>
407
- </tr>
408
- </table>
409
- </fieldset>
410
-
411
- <fieldset>
412
- <legend>Dev testing for book action bar</legend>
413
- <table class="initial">
414
- <tr colspan='5'>
415
- <td class="errorEnable"><label><input type="checkbox" name="errorEnable" value="errorEnable" />Do you want to see error response?</label></td>
416
- </tr>
417
- <tr>
418
- <td class="userState">
419
- <label><input type="checkbox" name="user" value="isAdmin" />isAdmin</label>
420
- <label><input type="checkbox" name="user" value="isLoggedIn" />isLoggedIn</label>
421
- </td>
422
- <td class="printDisabled">
423
- <label><input type="checkbox" name="is_printdisabled" value="is_printdisabled" />is_printdisabled</label>
424
- <label><input type="checkbox" name="user_is_printdisabled" value="user_is_printdisabled" />user_is_printdisabled</label>
425
- </td>
426
- <td class="availableToBrowse">
427
- <label><input type="radio" name="browse" value="available_to_browse" />available_to_browse</label>
428
- <label><input type="radio" name="browse" value="user_has_browsed" />user_has_browsed</label>
429
- <label><input type="radio" name="browse" value="browsingExpired" />browsingExpired</label>
430
- </td>
431
- <td class="availableToBorrow">
432
- <label><input type="radio" name="borrow" value="available_to_borrow" />available_to_borrow</label>
433
- <label><input type="radio" name="borrow" value="user_on_waitlist" />user_on_waitlist</label>
434
- <label><input type="radio" name="borrow" value="user_can_claim_waitlist" />user_can_claim_waitlist</label>
435
- <label><input type="radio" name="borrow" value="available_to_waitlist" />available_to_waitlist</label>
436
- <label><input type="radio" name="borrow" value="user_has_borrowed" />user_has_borrowed</label>
437
- </td>
438
- <td class="purchase">
439
- <label><input type="checkbox" name="purchase" value="purchase" />purchase</label>
440
- </td>
441
-
442
- <td class="reflect">
443
- <input type="button" style="padding: 10px;
444
- background: #194880;
445
- color: white;
446
- font-weight: bold; display: none" name="purchase" value="Reflect" />
447
- </td>
448
- </tr>
449
- <tr>
450
- <td>
451
- <fieldset style="margin-top: 10px;">
452
- <legend style="color: black;">controls for browsed book</legend>
453
- <table aria-hidden="true">
454
- <tbody><tr>
455
- <td class="action-button">
456
- <button id="show_warning_modal">When Browsing (`user_has_browsed`),<br> show Warning Modal</button>
457
- </td>
458
- <td class="action-button">
459
- <button id="show_expired_modal">While Browsing (`user_has_browsed`),<br> Expire book & show its modal</button>
460
- </td>
461
- <td class="action-button">
462
- <button id="resync_timer">While Browsing (`user_has_browsed`),<br> resync timer</button>
463
- </td>
464
- </tr>
465
- </tbody></table>
466
- </fieldset>
467
- </td>
468
- </tr>
469
- </table>
470
- </fieldset>
618
+ <div id="loan-status-row">
619
+ <fieldset>
620
+ <legend>WEBDEV-8322: loan duration for testing (reloads page)</legend>
621
+ <div class="timer-presets">
622
+ <button data-timer="15s">15 sec</button>
623
+ <button data-timer="30s">30 sec</button>
624
+ <button data-timer="2">2 min (default)</button>
625
+ <button data-timer="5">5 min</button>
626
+ <button data-timer="10">10 min</button>
627
+ <button data-timer="30">30 min</button>
628
+ <button data-timer="60">60 min (production default)</button>
629
+ </div>
630
+ <p style="color: #666; font-size: 11px; margin: 4px 0 0;">
631
+ Pick 15s/30s to watch the whole warn &rarr; auto-return &rarr; silent-reborrow
632
+ lifecycle play out on its own in under a minute, without clicking the scenario
633
+ buttons below.
634
+ </p>
635
+ </fieldset>
636
+
637
+ <fieldset>
638
+ <legend>WEBDEV-8322: live loan status (the action bar alone won't always make this obvious)</legend>
639
+ <div id="live-status-wrapper">
640
+ <span id="loan-status-badge" class="loan-status-badge status-none">NO LOAN</span>
641
+ <div id="live-status-detail">Not currently browsing this book</div>
642
+ </div>
643
+ <div id="exec-log"></div>
644
+ <p style="color: #666; font-size: 11px; margin: 4px 0 0; text-align: left;">
645
+ The badge flips to RETURNED the instant auto-return fires (scenario 2) — even though
646
+ no modal appears and the page doesn't refresh, per the ticket. The log below mirrors
647
+ every create_token / browse_book / renew_loan / return_loan call and its success/error
648
+ result as it happens.
649
+ </p>
650
+ <button id="clear-exec-log" style="margin-top: 6px; padding: 4px 8px; cursor: pointer;">Clear log</button>
651
+ </fieldset>
652
+ </div>
653
+ <div id="auto-renew-controls">
654
+ <fieldset style="margin-top: 10px;">
655
+ <legend style="color: black;">WEBDEV-8322: loan auto-renew QA scenarios (requires `user_has_browsed`)</legend>
656
+ <table aria-hidden="true">
657
+ <tbody><tr>
658
+ <td class="action-button">
659
+ <button id="show_warning_modal">1. Show "Are you still there?" modal<br>(Okay does NOT renew the loan)</button>
660
+ </td>
661
+ <td class="action-button">
662
+ <button id="show_expired_modal">2. Auto-return due to inactivity<br>(no modal, page stays put)</button>
663
+ </td>
664
+ <td class="action-button">
665
+ <button class="pageChangedEvent">3. Interact with book (turn page)<br>silently renew if interact in given time</button>
666
+ </td>
667
+ <td class="action-button">
668
+ <button id="resync_timer">4. Return to tab after time away<br>(visibilitychange — silent retry if expired)</button>
669
+ </td>
670
+ </tr>
671
+ </tbody></table>
672
+ <p style="color: #666; font-size: 11px; margin: 8px 0 0;">
673
+ Try 2 → 3 (or 2 → 4) in sequence to walk through the full "auto-returned, then patron
674
+ keeps reading" flow the ticket describes.
675
+ </p>
676
+ </fieldset>
677
+ </div>
678
+
679
+
680
+ <div id="lending-bar-controls">
681
+ <fieldset>
682
+ <legend>Dev testing for book title bar</legend>
683
+ <table class="initial">
684
+ <tr>
685
+ <td class="titleBar">
686
+ <label><input type="checkbox" name="title" value="title" />Title Bar</label>
687
+ </td>
688
+ <td class="searchParam">
689
+ <label><input type="checkbox" name="search" value="Search Param" />Search Param</label>
690
+ </td>
691
+ <td>
692
+ <label class="ia-button"><button class="pageChangedEvent">Page Change Event</button></label>
693
+ </td>
694
+ </tr>
695
+ </table>
696
+ </fieldset>
697
+
698
+ <fieldset>
699
+ <legend>Dev testing for book action bar</legend>
700
+ <table class="initial">
701
+ <tr colspan='5'>
702
+ <td class="errorEnable">
703
+ <label><input type="checkbox" name="errorEnable" value="errorEnable" />Do you want to see error response?</label>
704
+ <span style="color: #666; font-size: 11px; display: block; padding: 0 10px 10px;">
705
+ Tip: turn this on before scenarios 3/4 below to simulate someone else having
706
+ already borrowed the book (shows the "Due to inactivity..." modal).
707
+ </span>
708
+ </td>
709
+ </tr>
710
+ <tr>
711
+ <td class="userState">
712
+ <label><input type="checkbox" name="user" value="isAdmin" />isAdmin</label>
713
+ <label><input type="checkbox" name="user" value="isLoggedIn" />isLoggedIn</label>
714
+ </td>
715
+ <td class="printDisabled">
716
+ <label><input type="checkbox" name="is_printdisabled" value="is_printdisabled" />is_printdisabled</label>
717
+ <label><input type="checkbox" name="user_is_printdisabled" value="user_is_printdisabled" />user_is_printdisabled</label>
718
+ </td>
719
+ <td class="availableToBrowse">
720
+ <label><input type="radio" name="browse" value="available_to_browse" />available_to_browse</label>
721
+ <label><input type="radio" name="browse" value="user_has_browsed" />user_has_browsed</label>
722
+ <label><input type="radio" name="browse" value="browsingExpired" />browsingExpired</label>
723
+ </td>
724
+ <td class="availableToBorrow">
725
+ <label><input type="radio" name="borrow" value="available_to_borrow" />available_to_borrow</label>
726
+ <label><input type="radio" name="borrow" value="user_on_waitlist" />user_on_waitlist</label>
727
+ <label><input type="radio" name="borrow" value="user_can_claim_waitlist" />user_can_claim_waitlist</label>
728
+ <label><input type="radio" name="borrow" value="available_to_waitlist" />available_to_waitlist</label>
729
+ <label><input type="radio" name="borrow" value="user_has_borrowed" />user_has_borrowed</label>
730
+ </td>
731
+ <td class="purchase">
732
+ <label><input type="checkbox" name="purchase" value="purchase" />purchase</label>
733
+ </td>
734
+
735
+ <td class="reflect">
736
+ <input type="button" style="padding: 10px;
737
+ background: #194880;
738
+ color: white;
739
+ font-weight: bold; display: none" name="purchase" value="Reflect" />
740
+ </td>
741
+ </tr>
742
+ <tr>
743
+ <td>
744
+ </td>
745
+ </tr>
746
+ </table>
747
+ </fieldset>
748
+ </div>
749
+
471
750
  </div>
472
751
  <modal-manager></modal-manager>
473
752
  </body>
package/package.json CHANGED
@@ -3,11 +3,11 @@
3
3
  "description": "Bookreader actions for borrowable book",
4
4
  "repository": {
5
5
  "type": "git",
6
- "url": "git+https://github.com/internetarchive/iaux-account-settings.git"
6
+ "url": "git+https://github.com/internetarchive/iaux-book-actions.git"
7
7
  },
8
8
  "author": "Internet Archive",
9
9
  "license": "AGPL-3.0-only",
10
- "version": "1.4.2",
10
+ "version": "1.4.3-alpha1",
11
11
  "main": "index.js",
12
12
  "module": "index.js",
13
13
  "publishConfig": {
@@ -31,7 +31,6 @@
31
31
  "@internetarchive/local-cache": "^0.2.1",
32
32
  "@internetarchive/modal-manager": "^2.0.0",
33
33
  "@internetarchive/shared-resize-observer": "^0.2.0",
34
- "install-deps": "^1.1.0",
35
34
  "lit": "^2.8.0 || ^3.3.2"
36
35
  },
37
36
  "devDependencies": {