solutions table

This commit is contained in:
Egor Matveev 2021-12-18 10:21:13 +03:00
parent bd9ffa20bc
commit c2b1e67be5
10 changed files with 158 additions and 54 deletions

View File

@ -1,8 +1,10 @@
from functools import cached_property
from SprintLib.utils import get_bytes, write_bytes, delete_file from SprintLib.utils import get_bytes, write_bytes, delete_file
class FileStorageMixin: class FileStorageMixin:
@property @cached_property
def text(self): def text(self):
return get_bytes(self.fs_id).decode("utf-8") return get_bytes(self.fs_id).decode("utf-8")

View File

@ -1,4 +1,5 @@
from os.path import join, exists from functools import cached_property
from os.path import exists
from shutil import rmtree from shutil import rmtree
from subprocess import call from subprocess import call
@ -8,7 +9,7 @@ from django.utils import timezone
from Main.models.solution_file import SolutionFile from Main.models.solution_file import SolutionFile
from Main.models.task import Task from Main.models.task import Task
from Sprint.settings import CONSTS, SOLUTIONS_ROOT, SOLUTIONS_ROOT_EXTERNAL from Sprint.settings import CONSTS
from SprintLib.language import languages from SprintLib.language import languages
@ -28,7 +29,7 @@ class Solution(models.Model):
rmtree(self.directory) rmtree(self.directory)
super().delete(using=using, keep_parents=keep_parents) super().delete(using=using, keep_parents=keep_parents)
@property @cached_property
def files(self): def files(self):
data = [] data = []
for file in SolutionFile.objects.filter(solution=self): for file in SolutionFile.objects.filter(solution=self):

View File

@ -1,25 +1,58 @@
from django.http import HttpResponse from django.db.models import QuerySet
from Main.models import Solution from Main.models import Solution
from Sprint.settings import CONSTS from SprintLib.BaseView import BaseView, AccessError
from SprintLib.BaseView import BaseView
class SolutionsTableView(BaseView): class SolutionsTableView(BaseView):
view_file = "solutions_table.html" view_file = "solutions_table.html"
required_login = True required_login = True
endpoint = "solutions_table" endpoint = "solutions_table"
page_size = 20
page = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.filters = [
self.filter_user,
self.filter_task,
self.filter_set,
]
self.queryset = Solution.objects.all()
def filter_user(self, queryset: QuerySet):
if 'username' in self.request.GET:
return queryset.filter(user__username=self.request.GET["username"])
return queryset
def filter_task(self, queryset: QuerySet):
if 'task_id' in self.request.GET:
return queryset.filter(task_id=int(self.request.GET['task_id']))
return queryset
def filter_set(self, queryset: QuerySet):
if 'set_id' in self.request.GET:
return queryset.filter()
return queryset
def pre_handle(self):
if 'page' not in self.request.GET:
raise AccessError()
self.page = int(self.request.GET['page'])
if "username" in self.request.GET and self.request.user.username == self.request.GET['username']:
return
if hasattr(self.entities, "set"):
if self.entities.set.creator != self.request.user:
raise AccessError()
if hasattr(self.entities, "task"):
if self.entities.task.creator != self.request.user:
raise AccessError()
def get(self): def get(self):
self.context["solutions"] = Solution.objects.filter( for fltr in self.filters:
user=self.request.user, task=self.entities.task self.queryset = fltr(self.queryset)
).order_by("-time_sent") offset = self.page_size * (self.page - 1)
if "render" in self.request.GET.keys(): limit = self.page_size
return self.context["solutions"] = self.queryset.order_by("-id")[offset:offset + limit]
for sol in self.context["solutions"]: self.context["count_pages"] = range(1, (len(self.queryset) - 1) // self.page_size + 2)
if ( self.context["need_pagination"] = len(self.context["count_pages"]) > 1
sol.result == CONSTS["testing_status"]
or sol.result == CONSTS["in_queue_status"]
):
return
return HttpResponse("done")

View File

@ -0,0 +1,16 @@
from SprintLib.BaseView import BaseView
class SolutionsView(BaseView):
required_login = True
endpoint = "solutions"
view_file = "solutions.html"
def get(self):
self.context["username"] = self.request.GET.get("username")
self.context["task_id"] = self.request.GET.get("task_id")
if self.context["task_id"]:
self.context["task_id"] = int(self.context["task_id"])
self.context["set_id"] = self.request.GET.get("set_id")
if self.context["set_id"]:
self.context["set_id"] = int(self.context["set_id"])

View File

@ -1,5 +1,3 @@
from django.http import HttpResponse
from Main.models import Progress from Main.models import Progress
from SprintLib.BaseView import BaseView from SprintLib.BaseView import BaseView
@ -12,7 +10,3 @@ class TaskRuntimeView(BaseView):
def get(self): def get(self):
progress = Progress.objects.get(task=self.entities.task, user=self.request.user) progress = Progress.objects.get(task=self.entities.task, user=self.request.user)
self.context["progress"] = progress self.context["progress"] = progress
if "render" in self.request.GET.keys():
return
if progress.finished:
return HttpResponse("done")

View File

@ -13,4 +13,5 @@ from Main.views.SolutionView import SolutionView
from Main.views.ImageView import ImageView from Main.views.ImageView import ImageView
from Main.views.SendCodeView import SendCodeView from Main.views.SendCodeView import SendCodeView
from Main.views.SetSettingsView import SetSettingsView from Main.views.SetSettingsView import SetSettingsView
from Main.views.UsersView import UsersView from Main.views.UsersView import UsersView
from Main.views.SolutionsView import SolutionsView

44
templates/solutions.html Normal file
View File

@ -0,0 +1,44 @@
{% extends 'base_main.html' %}
{% block scripts %}
var page = 1;
function setPage(number) {
page = number;
}
function doPoll() {
jQuery.get('/solutions_table?task_id={{ task.id }}&page=' + page.toString(), function(data) {
document.getElementById('solutions').innerHTML = data;
const name = "page_num_" + page.toString();
document.getElementById(name).className = "btn btn-dark";
setTimeout(function() {doPoll()}, 2000);
})
}
{% endblock %}
{% block onload %}doPoll(){% endblock %}
{% block main %}
<h2>Решения</h2>
<h4>Фильтр</h4>
<div>
<select name="set_id" style="width: 33%">
<option value="0">Все сеты</option>
{% for set in user.userinfo.available_sets %}
<option value="{{ set.id }}" {% if set.id == set_id %}selected{% endif %}>{{ set.name }}</option>
{% endfor %}
</select>
<select name="set_id" style="width: 33%">
<option value="0">Все таски</option>
{% for task in user.userinfo.available_tasks %}
<option value="{{ task.id }}" {% if task.id == task_id %}selected{% endif %}>{{ task.name }}</option>
{% endfor %}
</select>
<select name="set_id" style="width: 33%">
<option value="0">Все пользователи</option>
{% for u in users %}
<option value="{{ user.username }}" {% if user.username == username %}selected{% endif %}>{{ user.userinfo }}</option>
{% endfor %}
</select>
</div>
<div id="solutions"></div>
{% endblock %}

View File

@ -1,8 +1,24 @@
<table class="table" style="margin-top: 30px;">
<thead>
<th scope="col">id</th>
<th scope="col">Пользователь</th>
<th scope="col">Задача</th>
<th scope="col">Время отправки</th>
<th scope="col">Язык</th>
<th scope="col">Результат</th>
</thead>
<tbody id="solutions">
{% for solution in solutions %} {% for solution in solutions %}
<tr> <tr>
<td> <td>
<b><a href="/solution?solution_id={{ solution.id }}">{{ solution.id }}</a></b> <b><a href="/solution?solution_id={{ solution.id }}">{{ solution.id }}</a></b>
</td> </td>
<td>
<img src="{{ solution.user.userinfo.profile_pic_url }}" width="30px" height="30px" style="border-radius: 50%; margin-right: 10px;"><a href="/account?username={{ solution.user.username }}">{{ solution.user }}</a>
</td>
<td>
<a href="/task?task_id={{ solution.task.id }}">{{ solution.task.name }}</a>
</td>
<td> <td>
{{ solution.time_sent }} {{ solution.time_sent }}
</td> </td>
@ -16,4 +32,17 @@
</h4> </h4>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody>
</table>
{% if need_pagination %}
<div style="display: flex; justify-content: flex-end">
<table>
<tr>
{% for num in count_pages %}
<td><button class="btn btn-light" id="page_num_{{ num }}" onclick="setPage({{ num }})">{{ num }}</button></td>
{% endfor %}
</tr>
</table>
</div>
{% endif %}

View File

@ -19,26 +19,20 @@
document.getElementById('file-upload').value = null; document.getElementById('file-upload').value = null;
document.getElementById('input0').value = ""; document.getElementById('input0').value = "";
} }
var page = 1;
function setPage(number) {
page = number;
}
function doPoll() { function doPoll() {
jQuery.get('/solutions_table?task_id={{ task.id }}', function(data) { jQuery.get('/solutions_table?task_id={{ task.id }}&username={{ user.username }}&page=' + page.toString(), function(data) {
document.getElementById('solutions').innerHTML = data;
const name = "page_num_" + page.toString();
document.getElementById(name).className = "btn btn-dark";
jQuery.get('/task_runtime?task_id={{ task.id }}', function(data1) { jQuery.get('/task_runtime?task_id={{ task.id }}', function(data1) {
if (data == 'done' && data1 == 'done') document.getElementById('runtime').innerHTML = data1;
return
if (data != 'done') {
document.getElementById('solutions').innerHTML = data;
}
if (data1 != 'done') {
document.getElementById('runtime').innerHTML = data1;
}
setTimeout(function() {doPoll()}, 2000); setTimeout(function() {doPoll()}, 2000);
}) })
}) })
jQuery.get('/solutions_table?id={{ task.id }}&render=true', function(data) {
document.getElementById('solutions').innerHTML = data;
})
jQuery.get('/task_runtime?id={{ task.id }}&render=true', function(data) {
document.getElementById('runtime').innerHTML = data;
})
} }
{% endblock %} {% endblock %}
@ -134,15 +128,5 @@
</form> </form>
<hr> <hr>
<h2>Решения</h2> <h2>Решения</h2>
<table class="table" style="margin-top: 30px;"> <div id="solutions"></div>
<thead>
<th scope="col">id</th>
<th scope="col">Время отправки</th>
<th scope="col">Язык</th>
<th scope="col">Результат</th>
</thead>
<tbody id="solutions">
</tbody>
</table>
{% endblock %} {% endblock %}

View File

@ -44,6 +44,6 @@
</tr> </tr>
</table> </table>
{% for task in tasks %} {% for task in tasks %}
<a href="/task?task_id={{ task.id }}">{{ task.name }}</a> {% if task.creator == user %}<a href="/admin/task?task_id={{ task.id }}"><i class="fa fa-pencil"></i> </a>{% endif %}<br> <a href="/task?task_id={{ task.id }}">{{ task.name }}</a> {% if task.creator == user %}<a href="/admin/task?task_id={{ task.id }}"><i class="fa fa-pencil"></i> </a><a href="/solutions?task_id={{ task.id }}&page=1"><i class="fa fa-stack-overflow"></i> </a>{% endif %}<br>
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}