-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
List Card Async Follow Functionality #11311
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
Changes from all commits
881775c
6867513
25f00fa
2dac08a
060ce9f
009b67e
873681c
81df69a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,5 @@ | ||||||||||
| import { buildPartialsUrl } from './utils' | ||||||||||
|
|
||||||||||
| import { PersistentToast } from './Toast' | ||||||||||
| /** | ||||||||||
| * Initializes lazy-loading the "Lists" section of Open Library book pages. | ||||||||||
| * | ||||||||||
|
|
@@ -44,6 +44,9 @@ export function initListsSection(elem) { | |||||||||
| } | ||||||||||
| // Initialize private buttons after content is loaded | ||||||||||
| initPrivateButtonsAfterLoad(listSection) | ||||||||||
|
|
||||||||||
| const followForms = listSection.querySelectorAll('.follow-form'); | ||||||||||
| initAsyncFollowing(followForms) | ||||||||||
|
Comment on lines
+48
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This needs to be here, as we are hydrating follow buttons that were asynchronously rendered. We should also query the page for and hydrate follow buttons in the main We'd likely also want to move the |
||||||||||
| }) | ||||||||||
| } | ||||||||||
| }) | ||||||||||
|
|
@@ -81,3 +84,42 @@ async function fetchPartials(workId, editionId) { | |||||||||
|
|
||||||||||
| return fetch(buildPartialsUrl('BPListsSection', params)); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| async function initAsyncFollowing(followForms) { | ||||||||||
| followForms.forEach(form => { | ||||||||||
| form.addEventListener('submit', async e => { | ||||||||||
| e.preventDefault(); | ||||||||||
| const url = form.action; | ||||||||||
| const formData = new FormData(form); | ||||||||||
| const submitButton = form.querySelector('button[type=submit]') | ||||||||||
| const stateInput = form.querySelector('input[name=state]') | ||||||||||
|
|
||||||||||
| const isFollowRequest = stateInput.value === '0' | ||||||||||
| const i18nStrings = JSON.parse(submitButton.dataset.i18n) | ||||||||||
| submitButton.disabled = true | ||||||||||
|
|
||||||||||
| await fetch(url, { | ||||||||||
| method: 'POST', | ||||||||||
| headers: { | ||||||||||
| 'Content-Type': 'application/x-www-form-urlencoded', | ||||||||||
| }, | ||||||||||
| body: new URLSearchParams(formData) | ||||||||||
| }) | ||||||||||
| .then(resp => { | ||||||||||
| if (!resp.ok) { | ||||||||||
| throw new Error('Network response was not ok'); | ||||||||||
| } | ||||||||||
| submitButton.classList.toggle('cta-btn--primary') | ||||||||||
| submitButton.classList.toggle('cta-btn--delete') | ||||||||||
| submitButton.textContent = isFollowRequest ? i18nStrings.unfollow : i18nStrings.follow | ||||||||||
| stateInput.value = isFollowRequest ? '1' : '0' | ||||||||||
| }) | ||||||||||
| .catch(() => { | ||||||||||
| new PersistentToast(i18nStrings.errorMsg).show(); | ||||||||||
| }) | ||||||||||
| .finally(() => { | ||||||||||
| submitButton.disabled = false | ||||||||||
| }); | ||||||||||
| }); | ||||||||||
| }); | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -21,19 +21,20 @@ | |||||
| $ img_url = img_url.replace("-S.jpg", "-M.jpg") | ||||||
| $else: | ||||||
| $ img_url = '/images/icons/avatar_book-sm.png' | ||||||
| <img src="$img_url" loading="lazy" width="80"/> | ||||||
| <img src="$img_url" alt="$_('Cover of book')" loading="lazy" width="80"/> | ||||||
| </a> | ||||||
|
|
||||||
| <!-- Bottom section: owner info or community label --> | ||||||
| $if owner: | ||||||
| <div class="list-follow-card__bottom"> | ||||||
| <div class="list-follow-card__user"> | ||||||
|
|
||||||
| $ owner_username = owner.key.split('/')[-1] | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| <a href="$owner.key"> | ||||||
| <img src="$(owner.key)/avatar" /> | ||||||
| <img src="$(owner.key)/avatar" alt="$_('Avatar of the owner of the list')" /> | ||||||
| </a> | ||||||
| <div class="list-follow-card__username"> | ||||||
| $if not own_list: | ||||||
| $ owner_username = owner.key.split('/')[-1] | ||||||
| <a class="list-follow-card__username-link" href="$owner.key" title="$owner_username"> | ||||||
| @${owner_username} | ||||||
| </a> | ||||||
|
|
@@ -45,7 +46,6 @@ | |||||
| </div> | ||||||
| <div class="list-follow-card__follow-button"> | ||||||
| $if not own_list: | ||||||
| $ owner_username = owner.key.split('/')[-1] | ||||||
| $ owner_account = get_user_object(owner_username) | ||||||
| $ is_subscribed = ctx.user and ctx.user.is_subscribed_user(owner_username) | ||||||
| $ settings = owner_account.get_users_settings() | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow, this is creating a "UnfollowFollow" entry in
messages.pot, here.This should probably be fixed in a separate PR. Will open an issue after this is merged.