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 #101 from unb-mds/feature/submission-page
Browse files Browse the repository at this point in the history
[feature request] Criar página de submissões
  • Loading branch information
bitterteriyaki authored Dec 1, 2023
2 parents 3bc85bb + bc49bd8 commit d8b21ab
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 5 deletions.
40 changes: 40 additions & 0 deletions apps/submissions/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.contrib.admin.sites import AdminSite
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext as _

Expand Down Expand Up @@ -94,3 +95,42 @@ def test_fieldsets(self) -> None:
(_("Details"), {"fields": ("author", "task", "code", "status")})
]
self.assertEqual(self.submission_admin.fieldsets, expected)


class SubmissionListViewtest(TestCase):
def setUp(self) -> None:
self.user = User.objects.create_user(
username="testuser",
email="testuser@example",
password="testpassword",
)

self.contest = Contest._default_manager.create(
title="Test Contest",
description="This is a test contest",
start_time=timezone.now(),
end_time=timezone.now() + timedelta(hours=1),
cancelled=False,
)

self.task = Task._default_manager.create(
title="Test Task",
description="This is a test task",
contest=self.contest,
)

self.submission = Submission._default_manager.create(
author=self.user,
task=self.task,
code="test code",
)

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

url = reverse("submissions:list")
response = self.client.get(url)

self.assertEqual(response.status_code, 200)
self.assertIn("submissions", response.context)
self.assertIn(self.submission, response.context["submissions"])
7 changes: 7 additions & 0 deletions apps/submissions/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path

from apps.submissions.views import SubmissionListView

app_name = "submissions"

urlpatterns = [path("", SubmissionListView.as_view(), name="list")]
21 changes: 21 additions & 0 deletions apps/submissions/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from typing import TYPE_CHECKING

from django.db.models import QuerySet
from django.views.generic import ListView

from apps.submissions.models import Submission

if TYPE_CHECKING:
SubmissionViewBase = ListView[Submission]
else:
SubmissionViewBase = ListView


class SubmissionListView(SubmissionViewBase):
model = Submission
template_name = "submissions/list.html"
context_object_name = "submissions"
paginate_by = 10

def get_queryset(self) -> QuerySet[Submission]:
return Submission._default_manager.all().order_by("-created_at")
12 changes: 8 additions & 4 deletions apps/tasks/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,12 @@ def test_handle_submission_with_exception(self) -> None:

code = "raise Exception('Test exception')"
response = self.client.post(self.url, data={"code": code})
url = reverse("submissions:list")

self.assertEqual(response.status_code, 302)
self.assertRedirects(
response,
self.url,
url,
status_code=302,
target_status_code=200,
fetch_redirect_response=True,
Expand All @@ -293,11 +294,12 @@ def test_handle_submission_with_correct_output(self) -> None:
self.task.save()

response = self.client.post(self.url, data={"code": self.code})
url = reverse("submissions:list")

self.assertEqual(response.status_code, 302)
self.assertRedirects(
response,
self.url,
url,
status_code=302,
target_status_code=200,
fetch_redirect_response=True,
Expand All @@ -309,19 +311,21 @@ def test_handle_submission_with_wrong_output(self) -> None:
self.task.output_file = "Hello, World!"
self.task.save()

url = reverse("submissions:list")
response = self.client.post(self.url, data={"code": self.code})

self.assertEqual(response.status_code, 302)
self.assertRedirects(
response,
self.url,
url,
status_code=302,
target_status_code=200,
fetch_redirect_response=True,
)

def test_form_success_url(self) -> None:
self.assertEqual(self.view.get_success_url(), self.url)
url = reverse("submissions:list")
self.assertEqual(self.view.get_success_url(), url)


class BackgroundJobTaskTest(TestCase):
Expand Down
2 changes: 1 addition & 1 deletion apps/tasks/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
return context

def get_success_url(self) -> str:
return reverse("tasks:detail", args=[self.object.id])
return reverse("submissions:list")

def get(
self,
Expand Down
1 change: 1 addition & 0 deletions server/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
path("contests/", include("apps.contests.urls"), name="contests"),
path("tasks/", include("apps.tasks.urls")),
path("", include("apps.users.urls")),
path("submissions/", include("apps.submissions.urls")),
]
7 changes: 7 additions & 0 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
}
</style>

{% block head %}{% endblock head %}

<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css"
Expand Down Expand Up @@ -70,6 +72,11 @@
Ranking
</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="{% url 'submissions:list' %}">
Submissions
</a>
</li>
</ul>
{% if request.user.is_authenticated %}
<div class="dropdown">
Expand Down
104 changes: 104 additions & 0 deletions templates/submissions/list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{% extends "base.html" %}

{% load crispy_forms_tags %}

{% block title %}Submissions{% 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>Submissions</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Submission ID</th>
<th>User</th>
<th>Task</th>
<th>Status</th>
<th>Created at</th>
</tr>
</thead>
<tbody>
{% for submission in page_obj %}
<tr>
<td>{{ submission.id }}</td>
<td>
<a href="{% url 'users:profile' submission.author.username %}">
{{ submission.author.username }}
</a>
</td>
<td>
<a href="{% url 'tasks:detail' submission.task.id %}">
{{ submission.task.title }}
</a>
</td>
<td>{{ submission.status }}</td>
<td>{{ submission.created_at }}</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 d8b21ab

Please sign in to comment.