diff --git a/app/blueprints/packages/reviews.py b/app/blueprints/packages/reviews.py index 5907159f..133f5a2a 100644 --- a/app/blueprints/packages/reviews.py +++ b/app/blueprints/packages/reviews.py @@ -16,7 +16,8 @@ from collections import namedtuple -from flask import render_template, request, redirect, flash, url_for, abort +import typing +from flask import render_template, request, redirect, flash, url_for, abort, jsonify from flask_babel import gettext, lazy_gettext from flask_login import current_user, login_required from flask_wtf import FlaskForm @@ -27,7 +28,7 @@ from app.models import db, PackageReview, Thread, ThreadReply, NotificationType, Permission, AuditSeverity, PackageState from app.tasks.webhooktasks import post_discord_webhook from app.utils import is_package_page, add_notification, get_int_or_abort, is_yes, is_safe_url, rank_required, \ - add_audit_log, has_blocked_domains + add_audit_log, has_blocked_domains, should_return_json from . import bp @@ -178,18 +179,16 @@ def delete_review(package, reviewer): return redirect(thread.get_view_url()) -def handle_review_vote(package: Package, review_id: int): +def handle_review_vote(package: Package, review_id: int) -> typing.Optional[str]: if current_user in package.maintainers: - flash(gettext("You can't vote on the reviews on your own package!"), "danger") - return + return gettext("You can't vote on the reviews on your own package!") review: PackageReview = PackageReview.query.get(review_id) if review is None or review.package != package: abort(404) if review.author == current_user: - flash(gettext("You can't vote on your own reviews!"), "danger") - return + return gettext("You can't vote on your own reviews!") is_positive = is_yes(request.form["is_positive"]) @@ -213,7 +212,15 @@ def handle_review_vote(package: Package, review_id: int): @login_required @is_package_page def review_vote(package, review_id): - handle_review_vote(package, review_id) + msg = handle_review_vote(package, review_id) + if should_return_json(): + if msg: + return jsonify({"success": False, "error": msg}), 403 + else: + return jsonify({"success": True}) + + if msg: + flash(msg, "danger") next_url = request.args.get("r") if next_url and is_safe_url(next_url): diff --git a/app/public/static/js/quick_review_voting.js b/app/public/static/js/quick_review_voting.js index 5ad364dd..970bad07 100644 --- a/app/public/static/js/quick_review_voting.js +++ b/app/public/static/js/quick_review_voting.js @@ -41,11 +41,24 @@ async function submitForm(form, is_helpful) { body: data, headers: { "Content-Type": "application/x-www-form-urlencoded", + "Accept": "application/json", }, }); if (!res.ok) { - console.error(await res.text()); + const json = await res.json(); + alert(json.error ?? "Unknown server error"); + } +} + + +function setButtonSelected(ele, isSelected) { + if (isSelected) { + ele.classList.add("btn-primary"); + ele.classList.remove("btn-secondary"); + } else { + ele.classList.add("btn-secondary"); + ele.classList.remove("btn-primary"); } } @@ -61,15 +74,16 @@ window.addEventListener("load", () => { if (not_selected.classList.contains("btn-primary")) { setVoteCount(not_selected, Math.max(getVoteCount(not_selected) - 1, 0)); - } - if (selected.classList.contains("btn-secondary")) { - setVoteCount(selected, getVoteCount(selected) + 1); + setButtonSelected(not_selected, false); } - selected.classList.add("btn-primary"); - selected.classList.remove("btn-secondary"); - not_selected.classList.add("btn-secondary"); - not_selected.classList.remove("btn-primary"); + if (selected.classList.contains("btn-secondary")) { + setVoteCount(selected, getVoteCount(selected) + 1); + setButtonSelected(selected, true); + } else if (selected.classList.contains("btn-primary")) { + setVoteCount(selected, Math.max(getVoteCount(selected) - 1, 0)); + setButtonSelected(selected, false); + } submitForm(helpful_form, is_helpful).catch(console.error); } diff --git a/app/templates/index.html b/app/templates/index.html index e8238efc..89fa4665 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -22,7 +22,7 @@ } {% if current_user.is_authenticated %} - + {% endif %} {% endblock %} diff --git a/app/templates/packages/reviews_list.html b/app/templates/packages/reviews_list.html index aee08f64..1975dd7f 100644 --- a/app/templates/packages/reviews_list.html +++ b/app/templates/packages/reviews_list.html @@ -6,7 +6,7 @@ {% block scriptextra %} {% if current_user.is_authenticated %} - + {% endif %} {% endblock %} diff --git a/app/templates/packages/view.html b/app/templates/packages/view.html index 1ebc773c..ff7b49f0 100644 --- a/app/templates/packages/view.html +++ b/app/templates/packages/view.html @@ -21,7 +21,7 @@ {% if current_user.is_authenticated %} - + {% endif %} {% endblock %} diff --git a/app/templates/threads/view.html b/app/templates/threads/view.html index 5d8114e8..391552a2 100644 --- a/app/templates/threads/view.html +++ b/app/templates/threads/view.html @@ -27,7 +27,7 @@ {% block scriptextra %} {% if current_user.is_authenticated %} - + {% endif %} {% endblock %} diff --git a/app/templates/users/profile.html b/app/templates/users/profile.html index cdb7f1fc..469799ea 100644 --- a/app/templates/users/profile.html +++ b/app/templates/users/profile.html @@ -10,7 +10,7 @@ {% block scriptextra %} {% if current_user.is_authenticated %} - + {% endif %} {% endblock %}