internetarchive / internetarchive/openlibrary

"Continue Reading" Phase 3: Merge Local Storage Read History into Carousel

Open
#13,274 1 comment 0 reactions 1 assignee Claimed by @Sadashii View on GitHub
Lead: @mekarpeles Metric: Retention Needs: Review Assignee Priority: 2 Theme: My Books
Dominant language
Python
Stars
6.7k
Forks
2k
Avg merge
2d 19h
Merged PRs (30d)
138

Description

> **Epic:** #13256 — "Continue Reading" Flow & Auto-Add Prompts *(open)*
> This is **Phase 3** of that epic. Check the epic issue for overall status and the dependency graph.

---

## Dependencies

The following issues must be merged before work begins on this phase:

- [ ] #13272 — Phase 1: Merge Active Loans & Loan History Carousel
- [ ] #13273 — Phase 2: Client-Side Read Tracking (Local Storage)

---

## Feature Request

### Problem / Opportunity

After Phase 1 (#13272) merges active CDL loans and loan history into a single carousel, and Phase 2 (#13273) captures open-access and browse interactions in `localStorage`, the two data sources still live in isolation. Patrons who read open-access books (which produce no server-side loan record) still see an empty dashboard when all their reading was done through "Read" or "Browse" links.

**Success:** After this ships, the "My Loans" carousel on My Books surfaces all three reading contexts — active loans, past loan history, and locally tracked open-access reads — so every patron who has touched at least one book sees a populated, personalized dashboard.

### Proposal

Extend the unified Loans carousel (built in Phase 1) to also incorporate the client-side `localStorage.ol_read_history` store (built in Phase 2) as a third, lowest-priority data source:

- On page load, read `localStorage.ol_read_history` entries in the frontend.
- Merge them with the server-rendered active loans + history list, deduplicating by OLID (server-side records take priority).
- Sort the final merged list by last-access timestamp descending.
- Render local-storage-only entries as lightweight cards (cover + title only; no loan action buttons since they are not active borrows).

This closes the gap for logged-out patrons and privacy-opt-out patrons: even if they have no server-side reading history, their locally tracked books appear in the carousel as a fallback.

**Depends on:** #13272 (Phase 1) and #13273 (Phase 2) being merged first.

This is Phase 3 of Epic #13256.

---

## Breakdown

Implementation Details (for maintainers)

#### Related files

Refer to [this map of common Endpoints](https://docs.openlibrary.org/developers/backend/endpoints.html):
* `openlibrary/plugins/openlibrary/js/my-books/store/readingHistory.js` — Phase 2 local storage store (read `getHistory()`)
* `openlibrary/templates/account/mybooks.html` — carousel template, needs a JS hook to merge local entries post-render
* `openlibrary/plugins/upstream/mybooks.py` — server-side carousel data assembly (Phase 1)
* `openlibrary/plugins/openlibrary/js/my-books/` — JS entry point for carousel augmentation logic [NEW file likely needed]

#### Requirements Checklist

* [ ] On page load, call `getHistory()` from the Phase 2 store to retrieve `localStorage.ol_read_history`
* [ ] Deduplicate against the server-rendered loan OLIDs (server-side wins on conflict)
* [ ] Inject local-storage-only entries as carousel cards (cover image + title, no loan action buttons)
* [ ] Sort final merged carousel by last-access timestamp descending
* [ ] Rename the carousel from **"My Loans"** to **"Continue Reading"** in `mybooks.html` and any associated i18n strings
* [ ] Gracefully handle missing cover images for local-storage entries (show placeholder)
* [ ] No carousel augmentation for logged-in patrons who have server-side data only (local fallback is additive, not replacing)
* [ ] Write JS unit tests for the merge/dedup/sort logic

#### Stakeholders

* @Sadashii (author, implementation lead)
* @mekarpeles (maintainer review)


#### Instructions for Contributors

* **Before** [creating a new branch](https://docs.openlibrary.org/developers/tools/git.html#making-changes-and-creating-a-pull-request) or pushing up changes to a PR, please first [run these commands](https://docs.openlibrary.org/developers/tools/git.html#working-on-your-branch) to ensure your repository is up to date, as the pre-commit bot may add commits to your PRs upstream.
* JS must be ESLint-compliant, use single quotes, and contain no jQuery.
* Run `npm run test:js` to validate merge/dedup logic unit tests pass.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.