Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
Merge pull request #111 from unb-mds/featureRequest/users-ranking-page
Browse files Browse the repository at this point in the history
[feature request]: Users ranking page
  • Loading branch information
bitterteriyaki authored Dec 9, 2023
2 parents 3c40dce + aa3eac9 commit 9a3c8ef
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 2 deletions.
29 changes: 29 additions & 0 deletions apps/users/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,32 @@ def test_email(self) -> None:

self.assertEqual(response.status_code, 200)
self.assertContains(response, user.email)


class RankingListViewtest(TestCase):
def setUp(self) -> None:
self.user = User._default_manager.create(
username="testuser1",
email="testuser@example1",
password="testpassword1",
score=100,
)
self.user = User._default_manager.create(
username="testuser2",
email="testuser@example2",
password="testpassword2",
score=90,
)

def test_ranking_list_view(self) -> None:
self.client.login(email="testuser@example", password="testpassword")

url = reverse("users:ranking")
response = self.client.get(url)
ranking_order = [user.username for user in response.context["ranking"]]
expected_order = ["testuser1", "testuser2"]

self.assertEqual(response.status_code, 200)
self.assertIn("ranking", response.context)
self.assertIn(self.user, response.context["ranking"])
self.assertEqual(ranking_order, expected_order)
3 changes: 2 additions & 1 deletion apps/users/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from django.urls import path

from apps.users.views import ProfileView, RegisterView
from apps.users.views import ProfileView, RankingView, RegisterView

app_name = "users"

urlpatterns = [
path("register/", RegisterView.as_view(), name="register"),
path("profile/<str:username>/", ProfileView.as_view(), name="profile"),
path("ranking/", RankingView.as_view(), name="ranking"),
]
19 changes: 19 additions & 0 deletions apps/users/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
from typing import TYPE_CHECKING

from django.contrib.auth import login
from django.db.models import QuerySet
from django.http import HttpRequest, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.views import View
from django.views.generic import ListView

from apps.users.forms import CreateUserForm
from apps.users.models import User

if TYPE_CHECKING:
RankingViewBase = ListView[User]
else:
RankingViewBase = ListView


class RegisterView(View):
template_name = "registration/register.html"
Expand Down Expand Up @@ -34,3 +43,13 @@ class ProfileView(View):
def get(self, request: HttpRequest, *, username: str) -> HttpResponse:
user = get_object_or_404(User, username=username)
return render(request, self.template_name, {"user": user})


class RankingView(RankingViewBase):
model = User
template_name = "ranking/list.html"
context_object_name = "ranking"
paginate_by = 10

def get_queryset(self) -> QuerySet[User]:
return User._default_manager.all().order_by("-score")
2 changes: 1 addition & 1 deletion templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
<li class="nav-item">
</li>
<li class="nav-item">
<a class="nav-link text-white" href="#">
<a class="nav-link text-white" href="{% url 'users:ranking' %}">
Ranking
</a>
</li>
Expand Down
96 changes: 96 additions & 0 deletions templates/ranking/list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{% extends "base.html" %}

{% load crispy_forms_tags %}

{% block title %}Ranking{% endblock title %}

{% block head %}
<style>
.center-table {
display: flex;
justify-content: center;
}
table {
border-collapse: collapse;
width: 100%;
margin: 20px 0;
}
th, td {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
</style>
{% endblock head %}

{% block content %}
<h2>Ranking</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Rank</th>
<th>User</th>
<th>Score</th>
</tr>
</thead>
<tbody>
{% for user in page_obj %}
<tr>
<td>{{ forloop.counter }}</td>
<td>
<a href="{% url 'users:profile' user.username %}">
{{ user.username }}
</a>
</td>
<td>{{ user.score }}</td>
</tr>
{% endfor %}
</tbody>
</table>

<nav aria-label="Page navigation example">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1" tabindex="-1">First</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">Previous</a>
</li>
{% endif %}

{% for i in page_obj.paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active">
<a class="page-link" href="?page={{ i }}">{{ i }} </a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}

{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" aria-disabled="true">Next</a>
</li>
{% endif %}
</ul>
</nav>
{% endblock content %}

0 comments on commit 9a3c8ef

Please sign in to comment.