Skip to content

Commit

Permalink
Merge pull request #5957 from jimchamp/feature/async-ratings
Browse files Browse the repository at this point in the history
Async star ratings
  • Loading branch information
mekarpeles authored Feb 3, 2022
2 parents 6cd1614 + c1c8eb2 commit 7a43409
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 13 deletions.
8 changes: 5 additions & 3 deletions openlibrary/macros/StarRatings.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
$ edition_key = edition.key if edition else ""
$ form_id = "ratingsForm%s" % id

<form id="$form_id" method="POST" action="$(work.key)/ratings.json"
<form class="star-rating-form" id="$form_id" method="POST" action="$(work.key)/ratings.json"
property="reviewRating" typeof="Rating" vocab="http://schema.org/">
<meta property="worstRating" content="1"/>
<meta property="bestRating" content="5"/>
Expand Down Expand Up @@ -50,6 +50,8 @@
</a>
</div>
</div>
$if rating:
<button type="submit" class="star-messaging">$_("Clear my rating")</button>
$ class_list = "star-messaging"
$if not rating:
$ class_list = "%s hidden" % (class_list)
<button type="submit" class="$class_list">$_("Clear my rating")</button>
</form>
4 changes: 2 additions & 2 deletions openlibrary/plugins/openlibrary/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def GET(self, work_id):
def POST(self, work_id):
"""Registers new ratings for this work"""
user = accounts.get_current_user()
i = web.input(edition_id=None, rating=None, redir=False, redir_url=None, page=None)
i = web.input(edition_id=None, rating=None, redir=False, redir_url=None, page=None, ajax=False)
key = (i.redir_url if i.redir_url else
i.edition_id if i.edition_id else
('/works/OL%sW' % work_id))
Expand Down Expand Up @@ -167,7 +167,7 @@ def response(msg, status="success"):
)
r = response('rating added')

if i.redir:
if i.redir and not i.ajax:
p = h.safeint(i.page, 1)
query_params = f'?page={p}' if p > 1 else ''
if i.page:
Expand Down
20 changes: 12 additions & 8 deletions openlibrary/plugins/openlibrary/js/Toast.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,18 @@ export class FadingToast extends Toast {
* @param {number} [timeout] Amount of time, in milliseconds, that the component will be visible
*/
constructor(message, $parent=null, timeout=DEFAULT_TIMEOUT) {
super(
// TODO(i18n-js)
$(`<div class="toast">
<span class="toast__body">${message}</span>
<a class="toast__close">&times;<span class="shift">Close</span></a>
</div>`),
$parent
);
// TODO(i18n-js)
const $toast = $(`<div class="toast">
<span class="toast__body">${message}</span>
<a class="toast__close">&times;<span class="shift">Close</span></a>
</div>`)

// Prevent sending null parent:
if ($parent) {
super($toast, $parent);
} else {
super($toast);
}
this.timeout = timeout;
}

Expand Down
62 changes: 62 additions & 0 deletions openlibrary/plugins/openlibrary/js/handlers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { FadingToast } from '../Toast.js';

export function initRatingHandlers(ratingForms) {
for (const form of ratingForms) {
form.addEventListener('submit', function(e) {
handleRatingSubmission(e, form);
})
}
}

function handleRatingSubmission(event, form) {
event.preventDefault();
// Continue only if selected star is different from previous rating
if (!event.submitter.classList.contains('star-selected')) {

// Construct form data object:
const formData = new FormData(form);
let rating;
if (event.submitter.value) {
rating = Number(event.submitter.value)
formData.append('rating', event.submitter.value)
}
formData.append('ajax', true);

// Make AJAX call
fetch(form.action, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams(formData)
})
.then((response) => {
if (!response.ok) {
throw new Error('Ratings update failed')
}
// Repaint stars
form.querySelectorAll('.star-selected').forEach((elem) => {
elem.classList.remove('star-selected');
if (elem.hasAttribute('property')) {
elem.removeAttribute('property');
}
})

const clearButton = form.querySelector('.star-messaging');
if (rating) {
clearButton.classList.remove('hidden');
form.querySelectorAll(`.star-${rating}`).forEach((elem) => {
elem.classList.add('star-selected');
if (elem.tagName === 'LABEL') {
elem.setAttribute('property', 'ratingValue')
}
})
} else {
clearButton.classList.add('hidden');
}
})
.catch((error) => {
new FadingToast(error.message).show();
})
}
}
7 changes: 7 additions & 0 deletions openlibrary/plugins/openlibrary/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,11 @@ jQuery(function () {
.find('details')
.removeAttr('open');
});

// Prevent default star rating behavior:
const ratingForms = document.querySelectorAll('.star-rating-form')
if (ratingForms) {
import(/* webpackChunkName: "star-ratings" */'./handlers')
.then((module) => module.initRatingHandlers(ratingForms));
}
});

0 comments on commit 7a43409

Please sign in to comment.