Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create My Books Dropper #8019

Merged
merged 41 commits into from
Sep 21, 2023

Conversation

jimchamp
Copy link
Collaborator

@jimchamp jimchamp commented Jun 29, 2023

Closes #6531
Closes #6897
Closes #6992
Closes #8009

Creates reusable dropper component, and refactors code such that the My Books dropper uses the new generic dropper.

Issue where works cannot added to / removed from a list has been fixed as well.

Technical

The Generic Dropper Component

The generic dropper component comprised of a primary button and dropdown content. The template for the dropper takes a rendered HTML string for each of these. The template also takes a additional classes as a string, enabling the dropper to be styled as needed.

generic-dropper-parts

Visibility of the dropdown content can be changed by clicking the "dropclick" arrow. If a patron clicks outside of the dropper component when the dropdown is visible, it will be hidden. This functionality is business as usual (BAU). What is new is that dropdown visibility can now be changed with 'toggle-dropperandclose-dropperevents. Using these new event is as easy as passing a reference to a child element of a dropper to thefireDropperToggleEventandfireDropperCloseEvent` functions, which dispatch the appropriate event from the given element to the parent dropper.

The new template for generic droppers is /openlibrary/templates/lib/dropper.html. All BAU dropper functionality will automatically be added to components created using that template.

The My Books Dropper

The My Books Dropper combines reading log shelf, list, and last read date management in a single component. Three new templates have been created for this component:

  • /openlibrary/templates/my_books/dropper.html: Takes a page (work, edition, author, etc.) and renders a new My Books Dropper
  • /openlibrary/templates/my_books/dropdown_content.html: Renders reading log buttons (if applicable), dropdown list affordances, and the "Create a new list" modal content.
  • /openlibrary/templates/my_books/primary_action.html: Renders the primary reading log button, or "Add to list" CTA button (depending on context).

New JS classes have been created in order to better encapsulate different "My Books" actions:

  • ReadingLogForms handles everything related to our reading log bookshelves.
  • ReadDateComponents contains code that toggles visibility of our "Last read date" components.
  • ReadingLists handles all list management functionality.

Additionally, a new MyBooksDropper class has been created, which creates instances of the aforementioned classes (if possible), and asynchronously loads the patrons lists. Creating a new MyBooksDropper object will hydrate all parts of the dropper that the object represents.

The following diagram illustrates which class affects what part of the My Books dropper:
my-books-dropper-main

Note that the ReadingList class also provides the "Remove from list" functionality for showcase items:
my-books-dropper-lists-showcase

General

The My Books droppers are feature flagged. Legacy "lists/widget" droppers will be used unless features.my_books_dropper is enabled in the openlibrary.yml. To quickly check if the new droppers are enabled, you can search the page's HTML source for the class dropper-wrapper, which is unique to My Books droppers.

New functions have been added to ListService.js which make /lists POST requests with fetch. The legacy, callback-based, approach was largely untestable.

Limitations

  • Lists can't be fully managed from search result pages currently (My Books reading log pages included). Items can be added to a list in this context, but not removed. This is due to the "Active Lists" showcase, which appears beneath the dropper on book pages, not being present in search results (too much vertical space needed).

Testing

When logged out:

  1. Clicking the dropper should not open it.
  2. Clicking the dropper should redirect to the login page.
  3. Droppers styling should not change.

When logged in, on a book page:

  1. All BAU dropper functionality on book pages works as expected.
  2. Clicking the "Use this work" checkbox should update the view appropriately.

When logged in, on a search result page:

  1. Books can be added to or removed from a reading log shelf (this is BAU).
  2. Works can be added to lists.
  3. No z-index issues observed while droppers are open.
  4. All list loading indicators are replaced. If the indicator in the second dropper has been replaced, they all should have been.
  5. Ensure that the correct item is being added to a list.

Screenshot

Next steps

We may want to avoid using the new My Books droppers until lists can be fully managed from search results pages. This will require list removal from inside of the dropdown content. Until that time, we could enable the droppers in testing in order to get feedback from folks.

We should also make sure that read date, list, and reading log data used to create these droppers is fetched in a performant manner (maybe in bulk and from a cache?).

After the feature is rolled out, we could consider the following improvements:

  • Create a dedicated template for the list showcases (found in the "Lists" section of the books page).
  • Remove unused legacy code (ReadingLogDropper.html, etc.).
  • Reevaluate the need for the lists/widget template.
  • Remove functions unused functions from ListService.js

Stakeholders

@jimchamp jimchamp force-pushed the refactor/generic-dropper branch 5 times, most recently from ef80d92 to 5448579 Compare July 4, 2023 00:39
@jimchamp jimchamp marked this pull request as ready for review July 4, 2023 00:42
@codecov-commenter
Copy link

codecov-commenter commented Jul 4, 2023

Codecov Report

Merging #8019 (78c0426) into master (c71ee55) will decrease coverage by 0.47%.
Report is 55 commits behind head on master.
The diff coverage is 15.15%.

@@            Coverage Diff             @@
##           master    #8019      +/-   ##
==========================================
- Coverage   17.14%   16.67%   -0.47%     
==========================================
  Files          71       83      +12     
  Lines        3750     4419     +669     
  Branches      647      757     +110     
==========================================
+ Hits          643      737      +94     
- Misses       2695     3199     +504     
- Partials      412      483      +71     
Files Changed Coverage Δ
openlibrary/plugins/openlibrary/js/index.js 0.00% <0.00%> (ø)
...ibrary/plugins/openlibrary/js/lists/ListService.js 0.00% <0.00%> (ø)
openlibrary/plugins/openlibrary/js/lists/index.js 6.20% <0.00%> (ø)
.../plugins/openlibrary/js/my-books/MyBooksDropper.js 0.00% <0.00%> (ø)
...y/js/my-books/MyBooksDropper/ReadDateComponents.js 0.00% <0.00%> (ø)
...library/js/my-books/MyBooksDropper/ReadingLists.js 0.00% <0.00%> (ø)
...rary/js/my-books/MyBooksDropper/ReadingLogForms.js 0.00% <0.00%> (ø)
...enlibrary/plugins/openlibrary/js/my-books/index.js 0.00% <0.00%> (ø)
...ary/plugins/openlibrary/js/my-books/store/index.js 20.00% <20.00%> (ø)
.../plugins/openlibrary/js/my-books/CreateListForm.js 25.00% <25.00%> (ø)
... and 4 more

... and 8 files with indirect coverage changes

@mekarpeles mekarpeles self-assigned this Jul 10, 2023
@mekarpeles mekarpeles added Priority: 1 Do this week, receiving emails, time sensitive, . [managed] Needs: Special Deploy This PR will need a non-standard deploy to production labels Jul 10, 2023
* @param {object} data Object containing the new list's name, description, and seeds.
* @returns {Promise<Response>} The results of the POST request
*/
export async function createList(userKey, data) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if there is a request error/failure?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing now, but maybe we trigger a toast message?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick note: any errors are meant to be handled by the caller of this function. Whatever we decide to do on list creation failure will be included inside of a catch() call, here:

await createList(this.userKey, data)
.then(response => response.json())
.then((data) => {
this.onListCreationSuccess(data['key'], listTitle)
})

@mekarpeles
Copy link
Member

Q: Is it possible for us to use a param or a separate endpoint (e.g addtolist.json v. addtolist) one which returns json upon POST and the other (think of the case where js is disabled on client) the result redirects patron back to (book) page.

The problem we'd be trying to solve is making the Want to Read button work more naturally in the case where js is disabled (so it doesn't look like a bug / return json)

@@ -62,8 +62,17 @@ def get_seed_info(doc):

@public
def get_list_data(list, seed, include_cover_url=True):
list_items = []
for s in list.get_seeds():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mekarpeles to check whether any caching here.

@jimchamp: may have performance issues if list has many seeds?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting that this section isn't properly feature-flagged. list_items should only be populated and added to list data d if my_books_dropper feature is enabled.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jimchamp: may have performance issues if list has many seeds?

Yes, on book pages. This is only called once on search results pages, but several times in book pages. The public get_user_lists function also calls this while iterating over a list. Cleaning up the lists widget template a bit should help.

@jimchamp jimchamp force-pushed the refactor/generic-dropper branch from 7078bf5 to fdc7e30 Compare July 18, 2023 20:28
@jimchamp
Copy link
Collaborator Author

jimchamp commented Jul 18, 2023

Checkmarks are now used inside of the droppers to indicate list membership. The active list showcase, previously located below the dropper on some pages, has been removed completely.

image
The dropper as found on an author page.

@@ -78,11 +78,11 @@
},
{
"path": "static/build/page-admin.css",
"maxSize": "25KB"
"maxSize": "26KB"
Copy link
Collaborator Author

@jimchamp jimchamp Jul 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that this size needed to be adjusted. I wonder if our Less references need investigation.

@jimchamp jimchamp force-pushed the refactor/generic-dropper branch from f1f55f3 to ec70452 Compare July 19, 2023 15:34
@@ -0,0 +1,17 @@
$def with(primary_button, dropdown_content, additional_classes='')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs comments. Would be good to know that passing generic-dropper--disabled as an additional class will disable the dropper for logged out patrons.

@jimchamp jimchamp added the Needs: Submitter Input Waiting on input from the creator of the issue/pr [managed] label Jul 26, 2023
@jimchamp
Copy link
Collaborator Author

Important Note: Feature flag should be reinstated. If we're seeing a severe performance hit on search pages after this is released, we'll want to be able to quickly revert to the old droppers.

@jimchamp jimchamp added the On testing.openlibrary.org This PR has been deployed to testing.openlibrary.org for testing label Jul 27, 2023
@jimchamp jimchamp force-pushed the refactor/generic-dropper branch 3 times, most recently from 456f6b5 to 946bc22 Compare August 7, 2023 15:31
Comment on lines 5 to 7
$ data_list_key = 'data-list-key=%s' % list.key if actionable else ''
<li $actionable $data_list_key>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @jimchamp do you mind if I commit this change? I think that should let both our PRs co-exist on testing (mine is #8168 )

Suggested change
$ data_list_key = 'data-list-key=%s' % list.key if actionable else ''
<li $actionable $data_list_key>
<li $actionable $:cond(actionable, 'data-list-key=%s' % list.key)>

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Messaged you on slack and you preferred to remove it from testing. Removed it 👍 Accept this suggestion at your discretion 😋

@cdrini cdrini removed the On testing.openlibrary.org This PR has been deployed to testing.openlibrary.org for testing label Aug 8, 2023
@jimchamp jimchamp force-pushed the refactor/generic-dropper branch from d4b7492 to 4c2a306 Compare August 9, 2023 17:51
@jimchamp jimchamp force-pushed the refactor/generic-dropper branch from bc6ed32 to ce0938f Compare September 12, 2023 19:25
- These are meant to be overridden by Dropper subclasses, if needed.
- `onDisabledClick` is called whenever a disable dropper is clicked
- `onOpen` is called when the dropper is opened
- `onClose` is called when the dropper is closed
- My Books dropper `toggleDropper` override has been replaced with an
`onOpen` override.
@jimchamp jimchamp removed the On testing.openlibrary.org This PR has been deployed to testing.openlibrary.org for testing label Sep 16, 2023
@jimchamp
Copy link
Collaborator Author

jimchamp commented Sep 16, 2023

Bugs fixed:

  • Author page rendering error
  • Clicking dropclick arrow while unauthenticated redirects to login page

Subclasses of Dropper no longer need to override toggleDropper() or closeDropper() to add additional functionality, as new on* event functions have been created:

  • onClose() is called when a dropper has been closed
  • onOpen() is called when a dropper has been opened
  • onDisabledClick() is called when the arrow of a disabled dropper has been clicked

The intention is that the new on* functions be overridden as needed.

New changes have not been deployed to LLEs.

@jimchamp jimchamp requested a review from mekarpeles September 16, 2023 00:54
Copy link
Member

@mekarpeles mekarpeles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, there were 4 considerations outstanding last time we discussed:

  1. Clicking dropdown arrow when logged out should redirect to login page
  2. Errors on Authors page
  3. Book covers not loading -- similar problems on production (at least for initial load)
  4. Create an issue for ability to see selected lists in dropper even when minimized/closed – volunteer wanted (limit to 3, scrollable)

@jimchamp jimchamp marked this pull request as draft September 18, 2023 15:26
@jimchamp jimchamp marked this pull request as ready for review September 19, 2023 16:21
@jimchamp jimchamp added the On testing.openlibrary.org This PR has been deployed to testing.openlibrary.org for testing label Sep 19, 2023
@mekarpeles mekarpeles merged commit eab5df4 into internetarchive:master Sep 21, 2023
@jimchamp jimchamp deleted the refactor/generic-dropper branch September 25, 2023 17:47
@jimchamp jimchamp removed the On testing.openlibrary.org This PR has been deployed to testing.openlibrary.org for testing label Apr 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Special Deploy This PR will need a non-standard deploy to production Priority: 1 Do this week, receiving emails, time sensitive, . [managed]
Projects
None yet
4 participants