Repository: internetarchive/openlibrary

Issue:
Yearly Reading Goals: Ability to jump to specific year
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->

**Deadline** 2023! Because we want some way to go to previous years, which is currently not possible without manipulating the URL.

### Describe the problem that you'd like solved
<!-- A clear and concise description of what you want to happen. -->

Currently on https://openlibrary.org/account/books/already-read (the "My Already Read Books" page), we see all books the patron has read.

There's a way (see yellow highlight) to jump to the **current** year's books only, not previous years.

![image](https://github.com/internetarchive/openlibrary/assets/978325/0982f318-3e93-4289-a594-8a86e5858160)

What we want to do is update My Books “Already Read” reading log page to have some way to go to a specific year.

### Requirements

Add a second dropdown **only** on the "Already Read" page (and **if** the patron has every set a yearly reading goal) that says, “All Time” or “2023”, “2022” where the dates are populated from the entries in their yearly-reading-goals db table…
![image](https://github.com/internetarchive/openlibrary/assets/978325/4434d2c3-220d-49b9-b6f6-1be7943bb9ef)

Add title to the page “My {year} Reading Goals” if a date is selected. Selecting a date should bring you to e.g. `https://openlibrary.org/account/books/already-read/year/{year}`

### Technical Solution
<!-- What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere? -->

<!-- Which suggestions or requirements should be considered for how feature needs to appear or be implemented? -->

Wrap the “crumb” dropper (for changing the page from e.g. "Currently Reading" to "Already Read") in a parent div container set to `display: flex` and if we’re on “Already Read” page then add a second “crumb” for the Year with default “All Time”.






Discussion:
Hello! I'd love to work on this issue. 
@mekarpeles I'd like to work on this issue. Can you assign it to me if possible?
how do we return list of years. Given function def get_reading_goals_year(): only returns current year

Resolving patch:
diff --git a/openlibrary/core/yearly_reading_goals.py b/openlibrary/core/yearly_reading_goals.py
--- a/openlibrary/core/yearly_reading_goals.py
+++ b/openlibrary/core/yearly_reading_goals.py
@@ -14,11 +14,10 @@ def create(cls, username: str, year: int, target: int):
 
     # Read methods:
     @classmethod
-    def select_by_username(cls, username: str):
+    def select_by_username(cls, username: str, order='year ASC'):
         oldb = db.get_db()
 
         where = 'username=$username'
-        order = 'year ASC'
         data = {
             'username': username,
         }
diff --git a/openlibrary/plugins/upstream/mybooks.py b/openlibrary/plugins/upstream/mybooks.py
--- a/openlibrary/plugins/upstream/mybooks.py
+++ b/openlibrary/plugins/upstream/mybooks.py
@@ -17,6 +17,7 @@
 from openlibrary.core.observations import Observations, convert_observation_ids
 from openlibrary.core.sponsorships import get_sponsored_editions
 from openlibrary.core.models import LoggedBooksData
+from openlibrary.core.yearly_reading_goals import YearlyReadingGoals
 
 
 RESULTS_PER_PAGE: Final = 25
@@ -215,6 +216,7 @@ def GET(self, username, year=None):
             # ensuring that the year is at least four digits long avoids incorrect results.
             raise web.badrequest(message="Year must be four digits")
         mb = MyBooksTemplate(username, 'already-read')
+        mb.selected_year = str(year)
         template = mybooks_readinglog().render_template(mb, year=year)
         return mb.render(template=template, header_title=_("Already Read"))
 
@@ -250,6 +252,15 @@ def render_template(self, mb, year=None):
         if include_ratings := mb.key == "already-read" and mb.is_my_page:
             logged_book_data.load_ratings()
 
+        # Add yearly reading goals to the MyBooksTemplate
+        if mb.key == 'already-read' and mb.is_my_page:
+            mb.reading_goals = [
+                str(result.year)
+                for result in YearlyReadingGoals.select_by_username(
+                    mb.username, order='year DESC'
+                )
+            ]
+
         ratings = logged_book_data.ratings
         return render['account/reading_log'](
             docs,
@@ -382,6 +393,9 @@ def __init__(self, username, key):
             else []
         )
 
+        self.reading_goals = []
+        self.selected_year = None
+
         if self.me and self.is_my_page:
             self.counts.update(PatronBooknotes.get_counts(self.username))
             self.sponsorships = get_sponsored_editions(self.user)


Test patch: