Add review votes page

This commit is contained in:
rubenwardy 2022-01-01 22:17:39 +00:00
parent e346587111
commit 8f4e214c52
3 changed files with 128 additions and 2 deletions

@ -13,6 +13,7 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from collections import namedtuple
from . import bp
@ -21,8 +22,8 @@ from flask_login import current_user, login_required
from flask_wtf import FlaskForm
from wtforms import *
from wtforms.validators import *
from app.models import db, PackageReview, Thread, ThreadReply, NotificationType, PackageReviewVote, Package
from app.utils import is_package_page, addNotification, get_int_or_abort, isYes, is_safe_url
from app.models import db, PackageReview, Thread, ThreadReply, NotificationType, PackageReviewVote, Package, UserRank
from app.utils import is_package_page, addNotification, get_int_or_abort, isYes, is_safe_url, rank_required
from app.tasks.webhooktasks import post_discord_webhook
@ -190,3 +191,34 @@ def review_vote(package, review_id):
return redirect(next_url)
else:
return redirect(review.thread.getViewURL())
@bp.route("/packages/<author>/<name>/review-votes/")
@rank_required(UserRank.ADMIN)
@is_package_page
def review_votes(package):
user_biases = {}
for review in package.reviews:
review_sign = 1 if review.recommends else -1
for vote in review.votes:
user_biases[vote.user.username] = user_biases.get(vote.user.username, [0, 0])
vote_sign = 1 if vote.is_positive else -1
vote_bias = review_sign * vote_sign
if vote_bias == 1:
user_biases[vote.user.username][0] += 1
else:
user_biases[vote.user.username][1] += 1
BiasInfo = namedtuple("BiasInfo", "username balance with_ against no_vote perc_with")
user_biases_info = []
for username, bias in user_biases.items():
total_votes = bias[0] + bias[1]
balance = bias[0] - bias[1]
perc_with = round((100 * bias[0]) / total_votes)
user_biases_info.append(BiasInfo(username, balance, bias[0], bias[1], len(package.reviews) - total_votes, perc_with))
user_biases_info.sort(key=lambda x: -abs(x.balance))
return render_template("packages/review_votes.html", form=form, package=package, reviews=package.reviews,
user_biases=user_biases_info)

@ -0,0 +1,89 @@
{% extends "base.html" %}
{% block title %}
{{ _("Review Votes") }}
{% endblock %}
{% block link %}
<a href="{{ package.getURL("packages.view") }}">{{ package.title }}</a>
{% endblock %}
{% block content %}
<h1>{{ _("Review votes on %(title)s by %(author)s", title=self.link(), author=package.author.display_name) }}</h1>
<h2>Helpful Biases</h2>
{% set total_reviews = reviews | length %}
<p>
This section shows whether users tend vote in a way that agrees or disagrees with a package.
Total reviews: {{ total_reviews }}.
</p>
<table class="table">
<thead>
<tr>
<th>Username</th>
<th>Balance</th>
<th>With Pkg</th>
<th>Against Pkg</th>
<th>No Vote</th>
</tr>
</thead>
<tbody>
{% for info in user_biases %}
{% set total_votes = info.with_ + info.against %}
<tr
{% if total_votes > 3 and total_votes > total_reviews * 0.5 and ((info.balance / total_votes) | abs) > 0.8 %}
style="color: #e74c3c;"
{% elif total_votes > 3 and ((info.balance / total_votes) | abs) > 0.9 %}
style="color: #f39c12;"
{% endif %}>
<td>{{ info.username }}</td>
<td>{{ info.balance }}</td>
<td>{{ info.with_ }} ({{ info.perc_with }}%)</td>
<td>{{ info.against }} ({{ 100 - info.perc_with }}%)</td>
<td>{{ info.no_vote }}</td>
</tr>
{% else %}
<tr><td colspan=3><i>No votes</i></td></tr>
{% endfor %}
</tbody>
</table>
<h2>Reviews</h2>
<table class="table">
{% for review in reviews %}
<tr>
<th colspan="2">
{% if review.recommends %}
<i class="fas fa-thumbs-up text-success mr-2"></i>
{% else %}
<i class="fas fa-thumbs-down text-danger mr-2"></i>
{% endif %}
<a href="{{ review.thread.getViewURL() }}">
{{ review.thread.title }}
</a> by {{ review.author.display_name }}
</th>
</tr>
<tr>
<td>
{% for vote in review.votes %}
{% if vote.is_positive %}
<a href="{{ url_for('users.profile', username=vote.user.username) }}" class="badge badge-secondary">
{{ vote.user.username }}
</a>
{% endif %}
{% endfor %}
</td>
<td>
{% for vote in review.votes %}
{% if not vote.is_positive %}
<a href="{{ url_for('users.profile', username=vote.user.username) }}" class="badge badge-secondary">
{{ vote.user.username }}
</a>
{% endif %}
{% endfor %}
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

@ -283,6 +283,11 @@
{% else %}
{{ render_review_preview(package) }}
{% endif %}
{% if current_user.is_authenticated and current_user.rank.atLeast(current_user.rank.ADMIN) %}
<a href="{{ package.getURL('packages.review_votes') }}" class="btn btn-secondary">Review Votes</a>
{% endif %}
{{ render_reviews(package.reviews, current_user) }}
{% if packages_uses %}