registration implemented
This commit is contained in:
90
templates/account.html
Normal file
90
templates/account.html
Normal file
@@ -0,0 +1,90 @@
|
||||
{% extends 'base_main.html' %}
|
||||
|
||||
{% block title %}Аккаунт{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<h2 style="margin-bottom: 40px;">Информация об аккаунте</h2>
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<div style="height: 100%; width: 100%;">
|
||||
<img src="{{ account.userinfo.profile_pic_url }}" height="100%" width="100%" alt="Фото профиля">
|
||||
</div>
|
||||
{% if owner %}
|
||||
<label for="file-upload" class="btn btn-light" style="margin-top: -100px; margin-left: 10%; width: 80%;">
|
||||
<i class="fa fa-upload"></i> Загрузить фото
|
||||
</label>
|
||||
<input type="file" form="photoform" style="display: none;" accept="image/png, image/jpg" class="btn form-control-file" id="file-upload" value="Выбрать файл" name="file" onchange="document.getElementById('photoform').submit();">
|
||||
<form method="POST" enctype="multipart/form-data" id="photoform">
|
||||
<input type="hidden" name="action" value="upload_photo">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<h3>
|
||||
{{ account.userinfo.surname }} {{ account.userinfo.name }} {{ account.userinfo.middle_name }}
|
||||
<span style="margin-left: 15px;" class="badge badge-{% if account.userinfo.activity_status == online_status %}success{% else %}secondary{% endif %}">{{ account.userinfo.activity_status }}</span>
|
||||
</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<h2><i class="fa fa-user"></i></h2>
|
||||
</td>
|
||||
<td><div style="width: 20px;"></div></td>
|
||||
<td>
|
||||
<p style="padding-top: 8px; font-size: 24px;">{{ account.username }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h2><i class="fa fa-at"></i></h2>
|
||||
</td>
|
||||
<td><div style="width: 20px;"></div></td>
|
||||
<td>
|
||||
<p style="padding-top: 8px; font-size: 24px;">{{ account.email }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h2><i class="fa fa-star"></i></h2>
|
||||
</td>
|
||||
<td><div style="width: 20px;"></div></td>
|
||||
<td>
|
||||
<p style="padding-top: 8px; font-size: 24px;">{{ account.userinfo.rating }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h2><i class="fa fa-arrow-up"></i></h2>
|
||||
</td>
|
||||
<td><div style="width: 20px;"></div></td>
|
||||
<td>
|
||||
<p style="padding-top: 8px; font-size: 24px;">{{ account.userinfo.place }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h2><i class="fa fa-calendar"></i></h2>
|
||||
</td>
|
||||
<td><div style="width: 20px;"></div></td>
|
||||
<td>
|
||||
<p style="padding-top: 8px; font-size: 24px;">{{ account.date_joined.date }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<hr><hr>
|
||||
{% if owner %}
|
||||
<p style="color: red;">{{ error_message }}</p>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="change_password">
|
||||
<h2 style="margin-bottom: 40px; margin-top: 40px;">Смена пароля</h2>
|
||||
<input type="password" placeholder="Текущий пароль" name="password" style="margin-bottom: 20px; width: 300px;"><br>
|
||||
<input type="password" placeholder="Новый пароль" name="new_password" style="margin-bottom: 20px; width: 300px;"><br>
|
||||
<input type="password" placeholder="Повторить пароль" name="repeat" style="margin-bottom: 20px; width: 300px;"><br>
|
||||
<button type="submit" class="btn btn-light">Сменить пароль</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
@@ -1,90 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Админка{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
.form {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function change() {
|
||||
let surname = document.getElementById('surname').value;
|
||||
let name = document.getElementById('name').value;
|
||||
let middle_name = document.getElementById('middle_name').value;
|
||||
let group = document.getElementById('group').value;
|
||||
let email = document.getElementById('email').value;
|
||||
let invite = document.getElementById('inviteButton');
|
||||
console.log(surname + ' ' + name + ' ' + middle_name + ' ' + group + ' ' + email);
|
||||
let dis = surname == '' || name == '' || middle_name == '' || group == '' || email == '' || email.indexOf('@') == -1 || email.indexOf('.') == -1 || email.indexOf('.') < email.indexOf('@');
|
||||
console.log(dis);
|
||||
invite.disabled = dis;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Доступные курсы</h2>
|
||||
{% for key, value in blocks.items %}
|
||||
<h5>{{ key.name }}</h5>
|
||||
{% for block in value %}
|
||||
<a href="/admin/block?id={{ block.id }}">{{ block.name }}</a><br>
|
||||
{% endfor %}
|
||||
{% if is_teacher %}
|
||||
<button type="button" class="btn btn-dark" data-toggle="modal" data-target="#example_{{ key.id }}" style="margin-top: 20px;">
|
||||
<i class="fa fa-plus-circle"></i> Новый блок
|
||||
</button>
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="example_{{ key.id }}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form method="POST">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitle">Новый блок в курсе {{ key.name }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{% csrf_token %}
|
||||
<input type="text" name="name" placeholder="Имя блока">
|
||||
<input type="hidden" name="course_id" value="{{ key.id }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-times-circle"></i> Закрыть</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-plus-circle"></i> Создать</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-dark" onclick="window.location.href = '/admin/users_settings?course_id={{ key.id }}'" style="margin-top: 20px;"><i class="fa fa-users"></i> Участники курса</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if is_superuser %}
|
||||
<h3 style="margin-top: 30px;">Пригласить пользователя</h3>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<input name="surname" placeholder="Фамилия" class="form" id="surname" onchange="change();"><br>
|
||||
<input name="name" placeholder="Имя" class="form" id="name" onchange="change();"><br>
|
||||
<input name="middle_name" placeholder="Отчество" class="form" id="middle_name" onchange="change();"><br>
|
||||
<input name="group" placeholder="Группа" class="form" id="group" onchange="change();"><br>
|
||||
<input name="email" placeholder="Почта" class="form" id="email" onchange="change();"><br>
|
||||
<button type="submit" id='inviteButton' name="invite" value="Пригласить" class="btn btn-dark" disabled>Пригласить</button>
|
||||
</form>
|
||||
<div>
|
||||
<center>
|
||||
<button target="_blank" rel="noopener noreferrer" type="submit" class="btn btn-dark" onclick="window.location.href = '/admin/'" value="Django admin"><i class="fa fa-shield"></i> Django admin</button>
|
||||
</center>
|
||||
</div>
|
||||
{% endif %}
|
||||
<center>
|
||||
<button class="btn btn-dark" style="margin-top: 20px;" onclick="window.location.href='/admin/docs'"><i class="fa fa-file"></i> Методичка</button>
|
||||
</center>
|
||||
{% endblock %}
|
@@ -26,37 +26,69 @@
|
||||
</script>
|
||||
<script type="text/javascript" src={% static "js/scripts.js" %}></script>
|
||||
<style type="text/css">
|
||||
.center {
|
||||
height: 400px;
|
||||
width: 400px;
|
||||
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -200px;
|
||||
margin-left: -200px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 500%;
|
||||
}
|
||||
.form {
|
||||
border: none;
|
||||
border-bottom: 2px solid;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
width: 300px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.sub {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.main_div {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.header {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
}
|
||||
.header-button {
|
||||
width: 170px;
|
||||
}
|
||||
.button-right {
|
||||
display: flex;
|
||||
}
|
||||
.task-settings-input {
|
||||
width: 50%;
|
||||
}
|
||||
.task-settings-textarea {
|
||||
height: 300px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px){
|
||||
.header-button {
|
||||
width:50px;
|
||||
}
|
||||
}
|
||||
{% block styles %}{% endblock %}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
|
||||
{% block scripts %}{% endblock %}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="{% block onload %}{% endblock %}">
|
||||
<div class="main_div">
|
||||
<header class="mt-2 mb-2" role="banner">
|
||||
<div class="row no-gutters top-buffer">
|
||||
<div class="col" style="min-width: 100px;">
|
||||
<button type="button" class="btn {% if current_page == 'main' %}btn-dark{% else %}btn-light{% endif %} btn-block top-button" onclick="main()"><i class="fa fa-random"></i> Sprint</button>
|
||||
</div>
|
||||
{% if is_admin %}
|
||||
<div class="col" style="min-width: 100px;">
|
||||
<button type="button" class="btn {% if current_page == 'admin' %}btn-dark{% else %}btn-light{% endif %} btn-block top-button" onclick="admin()"><i class="fa fa-user"></i> Админка</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="col" style="min-width: 100px;">
|
||||
<button type="button" class="btn {% if current_page == 'settings' %}btn-dark{% else %}btn-light{% endif %} btn-block top-button" onclick="settings()"><i class="fa fa-cog"></i> Настройки</button>
|
||||
</div>
|
||||
<div class="col-{% if is_admin %}8{% else %}9{% endif %}">
|
||||
|
||||
</div>
|
||||
<div class="col" style="min-width: 100px;">
|
||||
<button type="button" style="max-width: 200px;" class="btn btn-light btn-block top-button" onclick="logout()"><i class="fa fa-sign-out"></i> Выход</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{% block content %}{% endblock %}
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
35
templates/base_main.html
Normal file
35
templates/base_main.html
Normal file
@@ -0,0 +1,35 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="header">
|
||||
<button
|
||||
class="btn btn-light header-button"
|
||||
onclick="window.location.href='/'">
|
||||
<i class="fa fa-random"></i> Главная
|
||||
</button>
|
||||
<button class="btn btn-light header-button"
|
||||
onclick="window.location.href='/tasks'">
|
||||
<i class="fa fa-tasks"></i> Задачи
|
||||
</button>
|
||||
<button class="btn btn-light header-button"
|
||||
onclick="window.location.href='/sets'">
|
||||
<i class="fa fa-th-large"></i> Сеты
|
||||
</button>
|
||||
<button class="btn btn-light header-button"
|
||||
onclick="window.location.href='/rating'">
|
||||
<i class="fa fa-arrow-up"></i> Рейтинг
|
||||
</button>
|
||||
<div class="button-right" style="margin-top: -35px;">
|
||||
<button class="btn btn-light header-button"
|
||||
onclick="window.location.href='/account'">
|
||||
<i class="fa fa-user"></i> Аккаунт
|
||||
</button>
|
||||
<button class="btn btn-light header-button"
|
||||
onclick="window.location.href='/exit'">
|
||||
<i class="fa fa-sign-out"></i> Выход
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% block main %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
@@ -1,39 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}{{ Block.name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{{ Block.name }} {% if can_edit %}<a style="color: black;" href="/admin/block?id={{ Block.id }}"><i class="fa fa-pencil"></i></a> {% endif %}</h3>
|
||||
<h5>Таски</h5>
|
||||
<table>
|
||||
{% for task in Block.tasks %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/task?id={{ task.id }}">{{ task.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{% with mark=task|mark_for_task:user %}
|
||||
{% if mark|marked %}
|
||||
<div style="margin-left: 20px; border: 1px solid black; background: {{ mark|mark_color }}; width: 25px; text-align: center;">
|
||||
{{ mark }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if Block.show_rating %}
|
||||
<a href="/rating?block_id={{ Block.id }}" class="btn btn-dark" style="margin-top: 15px;"><i class="fa fa-star"></i> Рейтинг</a>
|
||||
{% endif %}
|
||||
<a href="/messages?block_id={{ Block.id }}" class="btn btn-dark" style="margin-top: 15px;"><i class="fa fa-comments"></i> Сообщения</a>
|
||||
<hr>
|
||||
{% if Block.opened %}
|
||||
Открыто для просмотра
|
||||
{% else %}
|
||||
Закрыто для просмотра
|
||||
{% endif %}
|
||||
<br>Доступно с <b>{{ Block.time_start }}</b> до <b>{{ Block.time_end }}</b>
|
||||
{% endblock %}
|
@@ -1,126 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}{{ Block.name }}|настройки{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function uploaded() {
|
||||
document.getElementById('is_uploaded').style.display = 'block';
|
||||
document.getElementById('is_uploaded').nodeValue = document.getElementById('file-upload').nodeValue;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{{ Block.name }} <a style="color: black;" href="/block?id={{ Block.id }}"><i class="fa fa-eye"></i></a></h3>
|
||||
<h5>Таски</h5>
|
||||
{% for task in Block.tasks %}
|
||||
<a href="/admin/task?id={{ task.id }}">{{ task.name }}</a><br>
|
||||
{% endfor %}
|
||||
{% if is_superuser %}
|
||||
<button type="button" class="btn btn-dark" data-toggle="modal" data-target="#example" style="margin-top: 20px;">
|
||||
<i class="fa fa-plus-circle"></i> Новый таск
|
||||
</button>
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="example" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form method="POST">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitle">Новый таск в блоке {{ Block.name }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{% csrf_token %}
|
||||
<input type="text" name="name" placeholder="Имя таска">
|
||||
<input type="hidden" name="block_id" value="{{ Block.id }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-times-circle"></i> Закрыть</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-plus-circle"></i> Создать</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<h5>Импортировать задачу из Я.Контест</h5>
|
||||
<form action="" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<label for="file-upload" class="btn btn-dark" style="margin-top: 20px;">
|
||||
<i class="fa fa-upload"></i> Загрузить архив
|
||||
</label>
|
||||
<span id="is_uploaded" style="display: none;">Архив загружен</span>
|
||||
<input type="file" class="btn form-control-file" id="file-upload" value="Выбрать файл" name="file" onchange="uploaded()">
|
||||
<br><button type="submit" value="Импортировать" class="btn btn-outline-dark"><i class="fa fa-play-circle"></i> Импортировать</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<hr>
|
||||
{% if is_superuser %}
|
||||
<h3>Ограничения по времени</h3>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="datetime-local" name="time_start" value="{{ Block.time_start_chrome }}">
|
||||
</td>
|
||||
<td>
|
||||
<input type="datetime-local" name="time_end" value="{{ Block.time_end_chrome }}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Открыто для просмотра<input type="checkbox" name="opened" style="margin-left:15px;" {{ Block.is_opened }}>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Показывать рейтинг участникам<input type="checkbox" name="rating" style="margin-left: 15px;" {% if Block.show_rating %}checked{% endif %}>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Приоритет <select name="priority">
|
||||
{% for i in 10|num_range %}
|
||||
<option {% if i == Block.priority %}selected{% endif %}>{{ i }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<button class="btn btn-dark" value="Установить" type="submit" style="margin-top: 20px;"><i class="fa fa-save"></i> Установить</button>
|
||||
</form>
|
||||
<hr>
|
||||
{% endif %}
|
||||
<div>
|
||||
<a class="btn btn-dark" href="/admin/rating?block_id={{ Block.id }}"><i class="fa fa-star"></i> Рейтинг</a>
|
||||
<button type="button" class="btn btn-dark" onclick="window.location.href = '/admin/solutions?block_id=' + {{ Block.id }}" value="Посмотреть решения"><i class="fa fa-list-ul"></i> Посмотреть решения</button>
|
||||
<a class="btn btn-dark" href="/admin/queue?block_id={{ Block.id }}"><i class="fa fa-align-left"></i> Очередь тестирования</a>
|
||||
<a class="btn btn-dark" href="/admin/cheating?block_id={{ Block.id }}"><i class="fa fa-bomb"></i> Проверка на списывание</a>
|
||||
{% if is_superuser %}
|
||||
<form method="POST" onsubmit="return confirm('Сейчас ты пытаешься сделать то, что может привести к серьезным последствиям. Если ты удалишь этот блок, то вместе с ним удалятся все таски, условия, тесты, дополнительные файлы и решения, сдаваемые в этот блок. Все данные будут безвозвратно утеряны. Оно нам надо?');">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="block_delete" value="{{ Block.id }}">
|
||||
<button type="submit" value="Удалить блок" class="btn btn-dark" style="margin-top: 10px;"><i class="fa fa-trash"></i> Удалить блок</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
<hr>
|
||||
{% endblock %}
|
@@ -1,133 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}{{ Block.name }} | списывание{% endblock %}
|
||||
|
||||
{% block links %}
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.4.0/build/styles/default.min.css">
|
||||
<script src="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.4.0/build/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function check_list(entity_type) {
|
||||
var cbox = document.getElementById('check_' + entity_type + '_all');
|
||||
var boxes = document.getElementsByClassName('check_' + entity_type);
|
||||
for (var i = 0; i < boxes.length; i++) {
|
||||
boxes[i].checked = cbox.checked;
|
||||
}
|
||||
}
|
||||
|
||||
function prepare_for_submit() {
|
||||
var conf = confirm('Точно запускаем проверку? Новую проверку можно будет запустить только после завершения данной');
|
||||
if (conf) {
|
||||
document.getElementById('main_form').submit();
|
||||
}
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>Списывание в <a href="/admin/block?id={{ Block.id }}">{{ Block.name }}</a></h3>
|
||||
<hr>
|
||||
<form method="POST" id="main_form">
|
||||
{% csrf_token %}
|
||||
<h5>Проверить таски</h5>
|
||||
<b><input type="checkbox" id="check_task_all" onchange="check_list('task')" checked> Все</b><br>
|
||||
{% for task in Block.tasks %}
|
||||
<input type="checkbox" class="check_task" name="check_task_{{ task.id }}" checked> {{ task.name }}<br>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
<h5>Проверить пользователей</h5>
|
||||
<b><input type="checkbox" id="check_user_all" onchange="check_list('user')" checked> Все</b><br>
|
||||
{% for sub in Block.course.students %}
|
||||
<input type="checkbox" class="check_user" name="check_user_{{ sub.user.id }}" checked> {{ sub.user.userinfo }}<br>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
<h5>Дополнительно</h5>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="best_result">
|
||||
</td>
|
||||
<td>
|
||||
Проверять только решения с лучшим результатом
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="last_solution">
|
||||
</td>
|
||||
<td>
|
||||
Проверять только последнее решение
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="all_tests">
|
||||
</td>
|
||||
<td>
|
||||
Проверять только прошедшие все тесты
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<select name="cheating_percent">
|
||||
{% for i in 100|num_range %}
|
||||
<option>{{ i }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
Какой процент схожести считать списыванием
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<button type="button" {% if Block.cheating_checking %}class="btn btn-secondary"{% else %}class="btn btn-dark" onclick="prepare_for_submit()"{% endif %}><i class="fa fa-rocket"></i> Запустить проверку</button>
|
||||
</form>
|
||||
<hr>
|
||||
<center><h1>{{ Block.cheating_status }}</h1></center>
|
||||
{% if Block.cheating_checked %}
|
||||
<h1>Результаты проверки</h1>
|
||||
{% for data in Block.cheating_results %}
|
||||
{% with user=data|user_by_id cheating_data=Block.cheating_results|dict_key:data %}
|
||||
<br><h3>{{ user.userinfo }} [{{ cheating_data|length }}]</h3>
|
||||
<button class="btn btn-link" onclick="var content = document.getElementById('div_{{ user.id }}'); content.hidden = !content.hidden;">Отчет</button>
|
||||
<div id="div_{{ user.id }}" hidden>
|
||||
{% for cheat in cheating_data %}
|
||||
{% with solution=cheat.solution|solution_by_id %}
|
||||
<div class="row">
|
||||
<div class="col-5">
|
||||
<h5><a href="/solution?id={{ solution.id }}">{{ solution.id }}</a> | {{ solution.user.userinfo }} | {{ cheat.file }}</h5>
|
||||
<pre>
|
||||
<code class="c# border border-dark">
|
||||
{{ solution|solution_file_text:cheat.file }}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<center>
|
||||
<a href="/task?id={{ solution.task.id }}">{{ solution.task.name }}</a><br>
|
||||
<b>{{ cheat.similarity }}%</b><br>
|
||||
<i class="fa fa-arrow-{% if cheat.source %}right{% else %}left{% endif %}"></i>
|
||||
</center>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
{% with solution2=cheat.similar|solution_by_id %}
|
||||
<h5><a href="/solution?id={{ solution2.id }}">{{ solution2.id }}</a> | {{ solution2.user.userinfo }} | {{ cheat.file }}</h5>
|
||||
<pre>
|
||||
<code class="c# border border-dark">
|
||||
{{ solution2|solution_file_text:cheat.file }}
|
||||
</code>
|
||||
</pre>
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
@@ -1,235 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Методичка{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
.screenshot {
|
||||
width: 100%;
|
||||
}
|
||||
.screenshot_div {
|
||||
margin-top: 20px;
|
||||
width: 80%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.code {
|
||||
padding: 15px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Методичка</h1>
|
||||
<hr>
|
||||
<h2><b>О системе</b></h2>
|
||||
<h3>Структура сервиса</h3>
|
||||
В сервисе существует два режима работы:
|
||||
<ul>
|
||||
<li>Режим студента</li>
|
||||
<li>Режим администратора</li>
|
||||
</ul>
|
||||
И одна компанента:
|
||||
<ul>
|
||||
<li>Darwin</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h3>Режим студента</h3>
|
||||
Режим студента показывает курсы, на которые подписан пользователь, а также блоки, содержащиеся в них.<br>
|
||||
Напротив каждого блока стоит (или отсутствует) оценка за данный блок.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/main_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
При нажатии на блок пользователь попадает в настройки выбранного блока.<br>
|
||||
На странице отображаются таски и (опционально) оценки за них.<br>
|
||||
Под списком тасков отображается информация о возможности отправки решений в блок, а также временной интервал активности блока.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/block_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
Страница таска представляет из себя подробное описание задания, предлагаемого к решению.<br>
|
||||
Описание таска содержит в себе следующие атрибуты:
|
||||
<ul>
|
||||
<li>Легена</li>
|
||||
<li>Формат входных данных</li>
|
||||
<li>Формат выходных данных</li>
|
||||
<li>Спецификации</li>
|
||||
</ul>
|
||||
Далее находится форма для отправки решения (.zip архив) и список отправленных решений.<br>
|
||||
Решение содержит в себе следующие атрибуты:
|
||||
<ul>
|
||||
<li>id</li>
|
||||
<li>Дата и время отправки</li>
|
||||
<li>Результат тестирования</li>
|
||||
<li>Оценка, выставленная преподавателем или ассистентом</li>
|
||||
<li>Комментарий к решению</li>
|
||||
</ul>
|
||||
Sprint поддерживает следующие варианты результатов тестирования:
|
||||
<ul>
|
||||
<li>M/N - решение прошло M тестов из N</li>
|
||||
<li>Time limit - превышен предел времени, отведенного на тестирование</li>
|
||||
<li>Compilation error - не удалось скомпилировать решение</li>
|
||||
<li>TEST ERROR - ошибка тестирования (может быть связана с некорректыми тестами)</li>
|
||||
<li>TESTING - решение находится в процессе тестирования</li>
|
||||
<li>IN QUEUE - решение находится в очереди на тестирование</li>
|
||||
</ul>
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/task_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
При нажатии на результат тестирование можно получить информацию о том, какие именно тесты были пройдены, а какие - нет.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/test_datails.png' %}" class="screenshot" />
|
||||
</div>
|
||||
При нажатии на id решения пользователь попадает на страницу решения.<br>
|
||||
Страница с решением содержит ту же информацию, что и на странице таска.<br>
|
||||
Помимо этого, на данной странице можно выставить оценку за решение и оставить комментарий. Для сохранения результата необходимо нажать на кнопку "Зачесть".<br>
|
||||
Для выставления оценки 0 или максимальной оценки за таск, необходимо нажать на кнопку "Незачесть" или "Выставить максимальный балл" соответственно.<br>
|
||||
Комментарий будет сохранен при нажатии на любую из кнопок.<br>
|
||||
Внизу страницы отображаются файлы решения, содержащие только символы Unicode, иначе говоря, файлы с кодом.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/solution_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
<hr>
|
||||
<h3>Режим администратора</h3>
|
||||
<i>Некоторые функции доступны только преподавателям</i><br>
|
||||
Главная страница режима администратора показывает доступные для администрирования курсы, блоки в них и ссылку на данную методичку.<br>
|
||||
Добавление нового блока в курс происходит по нажатии кнопки "Новый блок".
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/admin_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
При нажатии на кнопку "Участники курса" открывается страница с настройками участников курса.<br>
|
||||
Для подписки существующих студентов или преподавателей на курс, необходимо ввести в форму "Добавить участников" ФИО студента или email, на который зарегестрирован аккаунт.<br>
|
||||
Для подписки всех студентов определенной группы, нужно ввести название группы.<br>
|
||||
Для отписки студента от курса, нужно нажать на кнопку "отписка" рядом с нужным студентом.<br>
|
||||
Для того, чтобы сделать подписчика курса ассистентом или снятия с него таких прав, необходимо выбрать почту этого студента в форме "Назначить или разжаловать" и нажать на кнопку применить. Статус студента будет отображен в таблице ниже.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/users_settings_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
В Sprint отсутствует регистрация в обычном понимании данного термина, поэтому регистрация студентов происходит при первом добавлении его к некоторому курсу.<br>
|
||||
Прежде всего необходимо создать JSON файл по определенным правилам, описанным на странице участников курса.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/upload_rules.png' %}" class="screenshot" />
|
||||
</div>
|
||||
При нажатии на блок, отображается страница с настройками блока.<br>
|
||||
Страница настроек блока содержит следующие аттрибуты:
|
||||
<ul>
|
||||
<li>Набор тасков</li>
|
||||
<li>Интервал времени, в течение которого можно отправлять решения</li>
|
||||
<li>Решения, отправленные в данный блок</li>
|
||||
</ul>
|
||||
Ограничения по времени были внедрены для того, чтобы отложить запуск блока. Блок будет доступен студентам только если данный момент времени входит в интервал между временем начала и временем конца (границы включаются), и блок открыт для отправки решений.<br>
|
||||
После установки нужных значений необходимо нажать на кнопку "Сохранить".<br>
|
||||
Для создания нового таска после списка тасков есть кнопка "Новый таск".
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/admin_block_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
При нажатии на таск из списка, откроется страница с настройками таска.<br>
|
||||
Поля "Легенда", "Входные данные", "Выходные данные" и "Спецификации" заполняются с помощью html разметки, которая потом будет отображена в режиме студента.<br>
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/task_settings_page_1.png' %}" class="screenshot" />
|
||||
</div>
|
||||
В настройках таска содержатся еще несколько аттрибутов:
|
||||
<ul>
|
||||
<li>Ограничения по времени - количество миллисекунд, которое отводится на тестирование решения (целое число)</li>
|
||||
<li>Вес задачи - доля значимости таска в блоке (вещественное число, может быть больше единицы, а суммарно таски могут иметь вес отличный от единицы)</li>
|
||||
<li>Максимальная оценка - максмальная оценка, которую можно выставить за таск (целое число)</li>
|
||||
<li>Максимум решений - максимальное количество решений, которое можно отправить к таску (целое число, ограничение не действует на ассистентов и преподавателей)</li>
|
||||
</ul>
|
||||
В форму загрузки тестов загружается .cs файл с Unit тестами библиотеки Nunit. По нажатии на кнопку "Посмотреть" можно посмотреть тесты и отредактировать их. Для сохранения файла необходимо нажать на кнопку "Сохранить" внизу страницы.<br>
|
||||
В форму "Дополнительные файлы" можно загрузить файлы, которые будут скорированы в директорию с исполняемыми файлами при тестировании.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/task_settings_page_2.png' %}" class="screenshot" />
|
||||
</div>
|
||||
При нажатии на кнопку "Посмотреть решения" на странице настроек блока открывается страница решений, загруженных в текущий блок.<br>
|
||||
Функциональность таблицы решений внизу страницы схожа с подобной в режиме студента.<br>
|
||||
Фильтр на данной странице содержит следующие поля:
|
||||
<ul>
|
||||
<li>id - id решения</li>
|
||||
<li>Таск - имя таска</li>
|
||||
<li>Пользователь - почта студента</li>
|
||||
<li>Группа - решения от студентов из данной группы</li>
|
||||
<li>Последнее решение - последнее отправленное решение от каждого студента к каждому таску</li>
|
||||
<li>Лучший результат - решения с наибольшим количеством пройденных тестов от каждого студента к каждому таску</li>
|
||||
<li>Только студенты - исключить из фильтра решения от ассистентов и преподавателей</li>
|
||||
</ul>
|
||||
При нажатии на кнопку "Перетест" отфильтрованные решения будут перетестированы.
|
||||
<div class="border border-dark screenshot_div">
|
||||
<img src="{% static 'img/solutions_page.png' %}" class="screenshot" />
|
||||
</div>
|
||||
<hr>
|
||||
<h3>Darwin</h3>
|
||||
Одним из ограниений Unit тестирования является невозможность тестирования приватных методов и приватных классов.<br>
|
||||
Для решения данной проблемы в Sprint содержится компонента Darwin. Загрузить библиотеку можно по данной <a href="{% static '/files/Darwin.dll' %}" download>ссылке</a>.<br>
|
||||
Darwin позволяет создавать объекты приватных классов, задавать значения приватным полям и свойствам, а также вызывать приватные методы.<br>
|
||||
Основой библиотеки является класс <b>DObject</b>.<br>
|
||||
В конструктор передается имя того класса, объект которого необходимо создать, с указанием пространства имен.
|
||||
<div class="border border-dark code">
|
||||
<pre>
|
||||
using Darwin;
|
||||
using Nunit.Framework;
|
||||
|
||||
[TestFixture]
|
||||
public class Tests
|
||||
{
|
||||
[Test]
|
||||
public void Test1()
|
||||
{
|
||||
DObject d = new DObject("Calculator.Calc");
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
Для доступа к полям и свойствам класса нужно использовать индексатор.<br>
|
||||
<div class="border border-dark code">
|
||||
<pre>
|
||||
using Darwin;
|
||||
using Nunit.Framework;
|
||||
|
||||
[TestFixture]
|
||||
public class Tests
|
||||
{
|
||||
[Test]
|
||||
public void Test1()
|
||||
{
|
||||
DObject d = new DObject("Calculator.Calc");
|
||||
d["a"] = 5;
|
||||
Assert.AreEqual(d["a"], 5);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
Для вызова методов класса используется метод InvokeMethod.<br>
|
||||
В качетсве параметров передается имя метода и массив параметров.<br>
|
||||
Тип возвращаемого значения метода InvokeMethod - object, поэтому необходимо проводить каст к нужному типу после вызова.
|
||||
<div class="border border-dark code">
|
||||
<pre>
|
||||
using Darwin;
|
||||
using Nunit.Framework;
|
||||
|
||||
[TestFixture]
|
||||
public class Tests
|
||||
{
|
||||
[Test]
|
||||
public void Test1()
|
||||
{
|
||||
DObject d = new DObject("Calculator.Calc");
|
||||
d["a"] = 5;
|
||||
Assert.AreEqual(d["a"], 5);
|
||||
int val = (int)d.InvokeMethod("GetNumber", new object[] { d["a"] });
|
||||
Assert.AreEqual(val, d["a"]);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
<hr>
|
||||
<h2><b>Use cases</b></h2>
|
||||
<h3>Как собрать таск</h3>
|
||||
<hr>
|
||||
<h3>Как написать Unit тест правильно</h3>
|
||||
<hr>
|
||||
<h3>Как написать тест на входные и выходные данные</h3>
|
||||
<hr>
|
||||
<h3>Что необходимо указать в спецификациях</h3>
|
||||
<hr>
|
||||
<h3>Полезные html тэги</h3>
|
||||
{% endblock %}
|
@@ -1,67 +1,30 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
{% load static %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>
|
||||
Sprint
|
||||
</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href={% static "css/styles.css" %}>
|
||||
<script src="https://use.fontawesome.com/49b98aaeb5.js"></script>
|
||||
<script type="text/javascript" src={% static "js/scripts.js" %}></script>
|
||||
<style type="text/css">
|
||||
.center {
|
||||
height: 400px;
|
||||
width: 400px;
|
||||
{% extends 'base.html' %}
|
||||
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -200px;
|
||||
margin-left: -200px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 500%;
|
||||
}
|
||||
.form {
|
||||
border: none;
|
||||
border-bottom: 2px solid;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
width: 300px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.sub {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="center">
|
||||
<center>
|
||||
<div>
|
||||
<h1>
|
||||
<i class="fa fa-random"></i> Sprint
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
<p style="color: red;">{{ error_message }}</p>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="text" class="form" name="email" placeholder="email or username"><br>
|
||||
<input type="password" class="form" name="password" placeholder="password"><br>
|
||||
<input type="submit" value="Вход" class="sub btn btn-dark form">
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="window.location.href='/restore'" class="sub btn btn-dark form">Восстановить пароль</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="window.location.href='/register'" class="sub btn btn-dark form">Регистрация</button>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{% block title %}Вход{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="center">
|
||||
<center>
|
||||
<div>
|
||||
<h1>
|
||||
<i class="fa fa-random"></i> Sprint
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
<p style="color: red;">{{ error_message }}</p>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="text" class="form" name="email" placeholder="email or username"><br>
|
||||
<input type="password" class="form" name="password" placeholder="password"><br>
|
||||
<input type="submit" value="Вход" class="sub btn btn-dark form">
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="window.location.href='/restore'" class="sub btn btn-dark form">Восстановить пароль</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="window.location.href='/register'" class="sub btn btn-dark form">Регистрация</button>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
{% endblock %}
|
@@ -1,30 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
{% extends 'base_main.html' %}
|
||||
|
||||
{% block title %}Главная{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Доступные курсы</h2>
|
||||
{% for key, value in blocks.items %}
|
||||
<h5>{{ key.name }}</h5>
|
||||
{% for block in value %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/block?id={{ block.id }}">{{ block.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{% with mark=block|mark_for_block:user %}
|
||||
{% if mark|marked %}
|
||||
<div style="margin-left: 20px; border: 1px solid black; background: {{ mark|mark_color }}; width: 25px; text-align: center;">
|
||||
{{ mark }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% block main %}
|
||||
<h2>Мои группы</h2>
|
||||
{% endblock %}
|
@@ -1,31 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block content %}
|
||||
<h3 style="margin-bottom: 30px;">Сообщения</h3>
|
||||
{% for message in Block.messages %}
|
||||
<div class="row">
|
||||
<div class="col-2"></div>
|
||||
<div class="col-8" style="margin-bottom: 50px;">
|
||||
{% with userinfo=message.sender|userinfo_by_user %}
|
||||
<div style="background-color: #DDDDDD; padding: 15px;">
|
||||
<b>
|
||||
{{ userinfo }} | {{ userinfo.group }} |
|
||||
<a href="/{% if current_page == 'admin' %}admin/{% endif %}task?id={{ message.task.id }}">{{ message.task.name }}</a>
|
||||
{% if is_admin %} | <a href="/admin/solutions?block_id={{ Block.id }}&task_name={{ message.task.name }}&user={{ userinfo }}">Решения участника</a>{% endif %}
|
||||
</b>
|
||||
</div>
|
||||
<div class="border border-dark bg-light" style="padding: 30px;">
|
||||
{{ message.text }}
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-danger" style="right: 0;">Ответить всем</button>
|
||||
<button class="btn btn-success" style="right: 0;">Ответить</button>
|
||||
</div>
|
||||
{% endwith %}
|
||||
</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
@@ -1,33 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}{{ Block.name }} | очередь{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function doPoll() {
|
||||
jQuery.get('/queue_table?block_id={{ Block.id }}', function(data) {
|
||||
document.getElementById('body').innerHTML = data;
|
||||
setTimeout(function() {doPoll()}, 2000);
|
||||
})
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block onload %}doPoll(){% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3><a href="/admin/block?id={{ Block.id }}">{{ Block.name }}</a></h3>
|
||||
<h4>Очередь тестирования</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th scope="col">id</th>
|
||||
<th scope="col">Таск</th>
|
||||
<th scope="col">Дата и время отправки</th>
|
||||
<th scope="col">Студент</th>
|
||||
<th scope="col">Статус</th>
|
||||
</thead>
|
||||
<tbody id="body">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
@@ -1,19 +0,0 @@
|
||||
{% for solution in solutions %}
|
||||
<tr style="background-color: {% if solution.result == 'TESTING' %}#FFE2B7{% else %}{% if solution.result == 'IN QUEUE' %}#EAEAFF{% endif %}{% endif %};">
|
||||
<td>
|
||||
<b><a href="/admin/solution?id={{ solution.id }}">{{ solution.id }}</a></b>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/admin/task?id={{ solution.task.id }}">{{ solution.task.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.time_sent }}
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.userinfo.surname }} {{ solution.userinfo.name }} {{ solution.userinfo.middle_name }}
|
||||
</td>
|
||||
<td>
|
||||
<b>{{ solution.result }}</b>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
@@ -1,49 +1,34 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends 'base_main.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}Рейтинг{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>Рейтинг (beta)</h3>
|
||||
<h4><a style="color: black;" href="/{% if current_page == 'admin' %}admin/{% endif %}block?id={{ Block.id }}">{{ Block.name }}</a></h4>
|
||||
<table border="1px solid black" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Студент</th>
|
||||
{% for task in Block.tasks %}
|
||||
<th>{% if admin_course %}<a href="/admin/solutions?block_id={{ Block.id }}&task_name={{ task.name }}">{{ task.name }}</a>{% else %}{{ task.name }}{% endif %}</th>
|
||||
{% endfor %}
|
||||
<th scope="col" style="background-color: lightblue;">Оценка</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for sub in Block.course.students %}
|
||||
<tr>
|
||||
<th scope="row">{% if admin_course %}<a href="/admin/solutions?block_id={{ Block.id }}&user={{ sub.user|userinfo_by_user }}">{{ sub.user|userinfo_by_user }}</a>{% else %}{{ sub.user|userinfo_by_user }}{% endif %}</th>
|
||||
{% for task in Block.tasks %}
|
||||
{% with status=sub.user|mark_status:task %}
|
||||
<th style="background-color: {% if status == '-' %}white{% else %}{% if sub.user|fully_marked:task %}lime{% else %}yellow{% endif %}{% endif %};">
|
||||
{% if current_page == 'admin' and status != '-' %}
|
||||
<a style="color: black;" href="/admin/solutions?block_id={{ Block.id }}&user={{ sub.user|userinfo_by_user }}&task_name={{ task.name }}">{{ status }}</a>
|
||||
{% else %}
|
||||
{{ status }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
<td style="background-color: lightblue;">
|
||||
{% with mark=Block|mark_for_block:sub.user %}
|
||||
{% if mark|marked %}
|
||||
<div style="margin-left: 20px; border: 1px solid black; background: {{ mark|mark_color }}; width: 25px; text-align: center;">
|
||||
{{ mark }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<button class="btn btn-dark" style="margin-top: 30px;" onclick="window.location.href='/admin/download_rating?block_id={{ Block.id }}'">Скачать csv</button>
|
||||
{% block main %}
|
||||
<h4>Рейтинг</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style="text-align: center; vertical-align: middle; width: 70px;">#</th>
|
||||
<th scope="col" style="vertical-align: middle;">Пользователь</th>
|
||||
<th scope="col" style="vertical-align: middle;">Дата регистрации</th>
|
||||
<th scope="col" style="text-align: center; vertical-align: middle;">Рейтинг</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for u in users %}
|
||||
<tr {% if user == u %}style="background-color: #0000FF1E;"{% endif %}>
|
||||
<td style="text-align: center; vertical-align: middle; width: 70px;">
|
||||
{{ u.userinfo.place }}
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
<img src="{{ u.userinfo.profile_pic_url }}" width="50px" height="50px" style="border-radius: 50%;">
|
||||
<a href="/account?username={{ u.username }}">{{ u.username }}</a>
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
{{ u.date_joined.date }}
|
||||
</td>
|
||||
<td style="text-align: center; vertical-align: middle;">
|
||||
{{ u.userinfo.rating }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
@@ -1,29 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
{% load static %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>
|
||||
Sprint
|
||||
</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href={% static "css/styles.css" %}>
|
||||
<script type="text/javascript" src={% static "js/scripts.js" %}></script>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>
|
||||
<font color="black"><a href="/enter">Sprint</a></font>
|
||||
</h1>
|
||||
{{ error }}
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
{{ form }}
|
||||
</table>
|
||||
<input type="submit" value="Установить пароль" class="btn btn-dark" style="margin-top: 20px;">
|
||||
</form>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
{% load static %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>
|
||||
Восстановление пароля
|
||||
</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href={% static "css/styles.css" %}>
|
||||
<script type="text/javascript" src={% static "js/scripts.js" %}></script>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>
|
||||
<font color="black"><a href="{% url 'enter' %}">Sprint</a></font>
|
||||
</h1>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="black">Почта</font>
|
||||
</td>
|
||||
<td>
|
||||
<input type="email" name="email" class="input_simple">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="submit" value="Восстановить" class="btn btn-dark" style="margin-top: 20px;">
|
||||
</form>
|
||||
Если данный электронный адрес есть в базе, то на него будет отправлена ссылка для восстановления пароля.
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
47
templates/sets.html
Normal file
47
templates/sets.html
Normal file
@@ -0,0 +1,47 @@
|
||||
{% extends 'base_main.html' %}
|
||||
|
||||
{% block main %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Сеты</h2>
|
||||
</td>
|
||||
{% if user.userinfo.can_create %}
|
||||
<td>
|
||||
<button style="margin-left: 20px;" class="btn btn-success" data-toggle="modal" data-target="#example"><i class="fa fa-plus"></i></button>
|
||||
<div class="modal fade" id="example" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form method="POST">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitle">Создать новый сет</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{% csrf_token %}
|
||||
<input type="text" name="name" placeholder="Название сета">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-times-circle"></i> Закрыть</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-plus-circle"></i> Создать</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
{% for set in user.userinfo.available_sets %}
|
||||
<a href="/set?set_id={{ set.id }}">{{ set.name }}</a> {% if set.creator == user %}<a href="/admin/set?set_id={{ set.id }}"><i class="fa fa-pencil"></i> </a>{% endif %}<br>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
@@ -1,18 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Настройки{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>
|
||||
Сменить пароль
|
||||
</h2>
|
||||
<font color="red">{{ error }}</font>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
{{ form }}
|
||||
</table>
|
||||
<button type="submit" class="btn btn-dark" value="Сменить" style="margin-top: 20px;"><i class="fa fa-check"></i> Сменить</button>
|
||||
</form>
|
||||
<hr>
|
||||
{% endblock %}
|
@@ -1,271 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}{{ solution.task.name }}|решение{% endblock %}
|
||||
|
||||
{% block links %}
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.4.0/build/styles/default.min.css">
|
||||
<script src="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.4.0/build/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
{% endblock %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block scripts %}
|
||||
{% if can_edit %}
|
||||
function findGetParameter(parameterName) {
|
||||
var result = null,
|
||||
tmp = [];
|
||||
location.search
|
||||
.substr(1)
|
||||
.split("&")
|
||||
.forEach(function (item) {
|
||||
tmp = item.split("=");
|
||||
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function next() {
|
||||
const solutions_request = findGetParameter('solutions');
|
||||
const solutions = solutions_request.split(' ');
|
||||
const current = findGetParameter('id');
|
||||
const current_index = solutions.findIndex((element) => element == current);
|
||||
if (current_index != solutions.length - 1) {
|
||||
var next_element = document.getElementById('next');
|
||||
next_element.setAttribute('href', '/admin/solution?id=' + solutions[current_index + 1] + '&solutions=' + solutions_request);
|
||||
next_element.innerHTML = '->';
|
||||
}
|
||||
}
|
||||
function previous() {
|
||||
const solutions_request = findGetParameter('solutions');
|
||||
const solutions = solutions_request.split(' ');
|
||||
const current = findGetParameter('id');
|
||||
const current_index = solutions.findIndex((element) => element == current);
|
||||
if (current_index != 0) {
|
||||
var next_element = document.getElementById('previous');
|
||||
next_element.setAttribute('href', '/admin/solution?id=' + solutions[current_index - 1] + '&solutions=' + solutions_request);
|
||||
next_element.innerHTML = '<-';
|
||||
}
|
||||
}
|
||||
function fillContent() {
|
||||
next();
|
||||
previous();
|
||||
}
|
||||
{% if can_edit %}
|
||||
function showHideTests() {
|
||||
var text = document.getElementById('tests_text');
|
||||
var button = document.getElementById('tests_button');
|
||||
text.hidden = !text.hidden;
|
||||
if (text.hidden) {
|
||||
button.textContent = 'Показать тесты';
|
||||
} else {
|
||||
button.textContent = 'Скрыть тесты';
|
||||
}
|
||||
}
|
||||
function showHideLog() {
|
||||
var text = document.getElementById('log_text');
|
||||
var button = document.getElementById('log_button');
|
||||
text.hidden = !text.hidden;
|
||||
if (text.hidden) {
|
||||
button.textContent = 'Показать лог';
|
||||
} else {
|
||||
button.textContent = 'Скрыть лог';
|
||||
}
|
||||
}
|
||||
function retest() {
|
||||
let del = confirm("Подтвердите перетест");
|
||||
if (del) {
|
||||
const sols = findGetParameter('solutions');
|
||||
const link = '/admin/retest?block_id={{ solution.task.block.id }}&solution_id={{ solution.id }}&next={% autoescape off %}{{ path }}?id={{ solution.id }}{% if current_page == 'admin' %}%26solutions={% endif %}{% endautoescape %}'{% if current_page == 'admin' %} + sols.replaceAll(' ', '%20'){% endif %};
|
||||
window.location.href = link;
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block onload %}{% if can_edit %}fillContent(){% endif %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5>
|
||||
<form method="POST">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td>
|
||||
Блок
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% if current_page == 'admin' %}/admin{% endif %}/block?id={{ solution.task.block.id }}">{{ solution.task.block.name }}</a>
|
||||
{% if current_page == 'admin' %}
|
||||
| <a style="margin-top: 15px;" href="/admin/solutions?block_id={{ solution.task.block.id }}">К посылкам</a> | <a style="margin-top: 15px;" href="/admin/rating?block_id={{ solution.task.block.id }}">К рейтингу</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Таск
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% if current_page == 'admin' %}/admin{% endif %}/task?id={{ solution.task.id }}">{{ solution.task.name }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Студент
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.userinfo.surname }} {{ solution.userinfo.name }} {{ solution.userinfo.middle_name }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
id решения
|
||||
</td>
|
||||
<td>
|
||||
<div style="text-align: center;"></div>
|
||||
{% if can_edit %}
|
||||
<a id="previous"></a>
|
||||
{% endif %}
|
||||
{{ solution.id }}
|
||||
{% if can_edit %}
|
||||
<a id="next"></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Результат
|
||||
</td>
|
||||
<td>
|
||||
{% if can_edit or solution.task.show_details %}
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-link" data-toggle="modal" data-target="#resultModalLong{{ solution.id }}">
|
||||
{{ solution.result }}
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="resultModalLong{{ solution.id }}" tabindex="-1" role="dialog" aria-labelledby="resultModalLongTitle{{ solution.id }}" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="resultModalLongTitle{{ solution.id }}">Подробная информация о тестировании {{ solution.id }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{% autoescape off %}
|
||||
{{ solution.details }}
|
||||
{% endautoescape %}
|
||||
{% if can_edit %}
|
||||
<hr>
|
||||
<pre id="tests_text" hidden>
|
||||
<h4>Тесты</h4><br>
|
||||
{{ solution.task.tests_text }}
|
||||
</pre>
|
||||
<hr>
|
||||
<pre id="log_text" hidden>
|
||||
<h4>Лог</h4><br>
|
||||
{{ solution.log_text }}
|
||||
</pre>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{% if can_edit %}
|
||||
<button type="button" id="log_button" class="btn btn-warning" onclick="showHideLog()">Показать лог</button>
|
||||
<button type="button" id="tests_button" class="btn btn-primary" onclick="showHideTests()">Показать тесты</button>
|
||||
{% endif %}
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if solution.task.show_result %}
|
||||
{{ solution.result }}
|
||||
{% else %}
|
||||
Accepted
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Оценка
|
||||
</td>
|
||||
<td>
|
||||
{% if can_edit %}
|
||||
{% csrf_token %}
|
||||
<label>
|
||||
<select name="mark">
|
||||
{% autoescape off %}
|
||||
{{ solution.mark_select }}
|
||||
{% endautoescape %}
|
||||
</select>
|
||||
</label>
|
||||
{% else %}
|
||||
{% if solution.task.show_result %}
|
||||
{{ solution.mark_property }}
|
||||
{% else %}
|
||||
{% if solution.mark == null %}
|
||||
Checking
|
||||
{% else %}
|
||||
Checked
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Комментарий
|
||||
</td>
|
||||
<td>
|
||||
{% if can_edit %}
|
||||
<textarea rows="10" cols="50" style="resize: none;" name="comment">{{ solution.comment }}</textarea>
|
||||
{% else %}
|
||||
<pre>
|
||||
{{ solution.comment_property }}
|
||||
</pre>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% if can_edit %}
|
||||
<button type="submit" name="action" value="Зачесть" class="btn btn-dark"><i class="fa fa-check"></i> Зачесть</button>
|
||||
<button type="submit" name="action" value="Незачесть" class="btn btn-dark"><i class="fa fa-times"></i> Не зачесть</button>
|
||||
<button type="submit" name="action" value="Выставить макс. балл" class="btn btn-dark"><i class="fa fa-arrow-up"></i> Выставить макс. балл</button>
|
||||
<button type="button" class="btn btn-dark" onclick="retest()"><i class="fa fa-undo"></i> Перетест</button>
|
||||
{% endif %}
|
||||
<button type="button" class="btn btn-dark"><i class="fa fa-question-circle"></i> Помощь</button>
|
||||
</form>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Files</h3>
|
||||
{% for filename, text in solution.files.items %}
|
||||
<h5>{{ filename }}</h5>
|
||||
{% if filename|is_code %}
|
||||
<pre>
|
||||
<code class="c# border border-dark">
|
||||
{{ text }}
|
||||
</code>
|
||||
</pre>
|
||||
{% else %}
|
||||
<div class="border border-dark bg-light" style="padding: 15px;">
|
||||
<pre>
|
||||
{{ text }}
|
||||
</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
<hr>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
@@ -1,315 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}{{ Block.name }} | решения{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function filter() {
|
||||
const idi = document.getElementById('idi').value;
|
||||
const task = document.getElementById('task_name').value;
|
||||
const user = document.getElementById('user').value;
|
||||
const group = document.getElementById('group').value;
|
||||
const last_solution = document.getElementById('last_solution').checked;
|
||||
const best_result = document.getElementById('best_result').checked;
|
||||
const only_students = document.getElementById('only_students').checked;
|
||||
const not_seen = document.getElementById('not_seen').checked;
|
||||
var req = '';
|
||||
if (idi) {
|
||||
req += '&solution_id=' + idi;
|
||||
}
|
||||
if (not_seen) {
|
||||
req += '¬_seen=' + not_seen;
|
||||
}
|
||||
if (task) {
|
||||
req += '&task_name=' + task;
|
||||
}
|
||||
if (user) {
|
||||
req += '&user=' + user;
|
||||
}
|
||||
if (group) {
|
||||
req += '&group=' + group;
|
||||
}
|
||||
if (last_solution) {
|
||||
req += '&last_solution=' + last_solution;
|
||||
}
|
||||
if (best_result) {
|
||||
req += '&best_result=' + best_result;
|
||||
}
|
||||
if (only_students) {
|
||||
req += '&only_students=' + only_students;
|
||||
}
|
||||
window.location.href = '/admin/solutions?block_id={{ Block.id }}' + req;
|
||||
}
|
||||
function retest() {
|
||||
let del = confirm("Подтвердите перетест");
|
||||
if (del)
|
||||
window.location.href = '/admin/retest?block_id={{ Block.id }}{% autoescape off %}{{ req }}{% endautoescape %}';
|
||||
}
|
||||
function download() {
|
||||
let del = confirm("Подтвердите скачивание");
|
||||
if (del) {
|
||||
window.location.href = '/admin/download?block_id={{ Block.id }}{% autoescape off %}{{ req }}{% endautoescape %}';
|
||||
}
|
||||
}
|
||||
function showHideTests() {
|
||||
var text = document.getElementById('tests_text');
|
||||
var button = document.getElementById('tests_button');
|
||||
text.hidden = !text.hidden;
|
||||
if (text.hidden) {
|
||||
button.textContent = 'Показать тесты';
|
||||
} else {
|
||||
button.textContent = 'Скрыть тесты';
|
||||
}
|
||||
}
|
||||
function showHideLog() {
|
||||
var text = document.getElementById('log_text');
|
||||
var button = document.getElementById('log_button');
|
||||
text.hidden = !text.hidden;
|
||||
if (text.hidden) {
|
||||
button.textContent = 'Показать лог';
|
||||
} else {
|
||||
button.textContent = 'Скрыть лог';
|
||||
}
|
||||
}
|
||||
function fillModalResults(id) {
|
||||
jQuery.get('/get_result_data?id=' + id, function(data) {
|
||||
const response = JSON.parse(data);
|
||||
if (response['success'] == true) {
|
||||
document.getElementById('resultModalLongTitle').innerHTML = 'Подробная информация о тестировании ' + id;
|
||||
document.getElementById('results_text').innerHTML = response['results_text'];
|
||||
document.getElementById('tests_text').innerHTML = '<h4>Тесты</h4><br>' + response['tests_text'];
|
||||
document.getElementById('log_text').innerHTML = '<h4>Лог</h4><br>' + response['log_text'];
|
||||
}
|
||||
});
|
||||
}
|
||||
function fillModalComments(id) {
|
||||
jQuery.get('/get_comment_data?id=' + id, function(data) {
|
||||
const response = JSON.parse(data);
|
||||
if (response['success'] == true) {
|
||||
document.getElementById('commentModalLongTitle').innerHTML = 'Комментарий к решению ' + id;
|
||||
document.getElementById('comment_text').innerHTML = response['comment_text'];
|
||||
}
|
||||
});
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
.input_field {
|
||||
width: 500px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="resultModalLong" tabindex="-1" role="dialog" aria-labelledby="resultModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="resultModalLongTitle"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div id="results_text"></div>
|
||||
<hr>
|
||||
<pre id="tests_text" hidden></pre>
|
||||
<hr>
|
||||
<pre id="log_text" hidden></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" id="log_button" class="btn btn-warning" onclick="showHideLog()">Показать лог</button>
|
||||
<button type="button" id="tests_button" class="btn btn-primary" onclick="showHideTests()">Показать тесты</button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="commentModalLong" tabindex="-1" role="dialog" aria-labelledby="commentModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentModalLongTitle"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<pre id="comment_text"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2><a href="/admin/block?id={{ Block.id }}">{{ Block.name }}</a></h2>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h4>Фильтр</h4>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Id</td>
|
||||
<td><input class="input_field" type="text" placeholder="Id" id="idi" name="idi" value="{{ options.solution_id }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Таск</td>
|
||||
<td>
|
||||
<select class="input_field" id="task_name" name="task_name">
|
||||
<option value="">Все</option>
|
||||
{% for task in solutions_info.tasks %}
|
||||
<option value="{{ task.name }}" {% if options.task_name == task.name %}selected{% endif %}>{{ task.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Пользователь</td>
|
||||
<td>
|
||||
<select class="input_field" id="user" name="user">
|
||||
<option value="">Все</option>
|
||||
{% for u in solutions_info.users %}
|
||||
<option value="{{ u }}" {% if options.user == u %}selected{% endif %}>{{ u }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Группа</td>
|
||||
<td>
|
||||
<select class="input_field" id="group" name="group">
|
||||
<option value="">Все</option>
|
||||
{% for group in solutions_info.groups %}
|
||||
<option value="{{ group }}" {% if options.group == group %}selected{% endif %}>{{ group }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Последнее решение</td>
|
||||
<td><input type="checkbox" id="last_solution" name="last_solution" {% if options.last_solution %}checked{% endif %}>{{ option.last_solution }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Лучший результат</td>
|
||||
<td><input type="checkbox" id="best_result" name="best_result" {% if options.best_result %}checked{% endif %}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Только студенты</td>
|
||||
<td><input type="checkbox" id="only_students" name="only_students" {% if options.only_students %}checked{% endif %}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Еще не проверено</td>
|
||||
<td><input type="checkbox" id="not_seen" name="not_seen" {% if options.not_seen %}checked{% endif %}></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-dark" id="control" onclick="filter()" style="margin-top: 20px;"><i class="fa fa-check"></i> Применить</button><br>
|
||||
<button type="button" class="btn btn-dark" id="control" onclick="window.location.href='/admin/solutions?block_id={{ Block.id }}'" style="margin-top: 10px;"><i class="fa fa-times"></i> Сбросить</button><br>
|
||||
<button style="margin-top: 10px;" class="btn btn-dark" onclick="download()"><i class="fa fa-download"></i> Скачать решения</button><br>
|
||||
<button style="margin-top: 10px;" class="btn btn-dark" onclick="retest()"><i class="fa fa-undo"></i> Перетест</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h4>Статистика по таскам</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th scope="col">Таск</th>
|
||||
<th scope="col">Верно</th>
|
||||
<th scope="col">Частично</th>
|
||||
<th scope="col">С ошибкой</th>
|
||||
<th scope="col">Все</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for task in Block.tasks %}
|
||||
<tr>
|
||||
<th scope="row">{{ task.name }}</th>
|
||||
<td>{{ task.correct_count }}</td>
|
||||
<td>{{ task.partially_passed }}</td>
|
||||
<td>{{ task.solutions_with_error }}</td>
|
||||
<td>{{ task.solutions_count }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<h5>Решения</h5>
|
||||
<form method="POST" id="delete_form">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<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>
|
||||
<th scope="col">Оценка</th>
|
||||
<th scope="col">Комментарий</th>
|
||||
<th scope="col">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for solution in solutions %}
|
||||
<tr style="background-color: {% if solution.result == 'TESTING' %}#FFE2B7{% else %}{% if solution.result == 'IN QUEUE' %}#EAEAFF{% endif %}{% endif %};">
|
||||
<th scope="row">
|
||||
<a href="/admin/solution?id={{ solution.id }}&solutions={{ filter }}">{{ solution.id }}</a>
|
||||
</th>
|
||||
<td>
|
||||
<a href="/admin/task?id={{ solution.task.id }}">{{ solution.task.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.userinfo.surname }} {{ solution.userinfo.name }} {{ solution.userinfo.middle_name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.time_sent }}
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.userinfo.group }}
|
||||
</td>
|
||||
<td>
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-link" data-toggle="modal" data-target="#resultModalLong" onclick="fillModalResults({{ solution.id }})">
|
||||
{{ solution.result }}
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.mark_property }}
|
||||
</td>
|
||||
<td>
|
||||
{% if solution.comment %}
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-link" data-toggle="modal" data-target="#commentModalLong" onclick="fillModalComments({{ solution.id }})">
|
||||
Посмотреть
|
||||
</button>
|
||||
{% else %}
|
||||
<p>Нет комментария</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-primary" onclick="window.location.href='/admin/download?block_id={{ Block.id }}&solution_id={{ solution.id }}';"><i class="fa fa-download"></i></button>
|
||||
<button name="DELETE_SOLUTION" form="delete_form" value="{{ solution.id }}" onclick="var del = confirm('Подтвердите удаление');if (del){this.form.submit();}" class="btn btn-danger" type="игеещт"><i class="fa fa-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
@@ -1,45 +1,19 @@
|
||||
{% for solution in solutions %}
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<a href="/solution?id={{ solution.id }}">{{ solution.id }}</a>
|
||||
</th>
|
||||
<td>
|
||||
{{ solution.time_sent }}
|
||||
</td>
|
||||
<td>
|
||||
{% if can_edit or task.show_details %}
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-link" data-toggle="modal" data-target="#resultModalLong" onclick="showData('{{ solution.id }}')">
|
||||
{{ solution.result }}
|
||||
</button>
|
||||
<div id="details_{{ solution.id }}" hidden>{% autoescape off %}{{ solution.details }}{% endautoescape %}</div>
|
||||
{% if can_edit %}
|
||||
<div id="tests_{{ solution.id }}" hidden>{{ solution.task.tests_text }}</div>
|
||||
<div id="log_{{ solution.id }}" hidden>{% autoescape off %}{{ solution.log_text }}{% endautoescape %}</div>
|
||||
{% endif %}
|
||||
{% else %}{% if task.show_result %}
|
||||
{{ solution.result }}
|
||||
{% else %}
|
||||
Accepted
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
<td>
|
||||
{% if task.show_result or can_edit %}
|
||||
{{ solution.mark_property }}
|
||||
{% else %}
|
||||
{% if solution.mark == null %}
|
||||
Checking
|
||||
{% else %}
|
||||
Checked
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<pre>
|
||||
{{ solution.comment_property }}
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><a href="">{{ solution.id }}</a></b>
|
||||
</td>
|
||||
<td>
|
||||
{{ solution.time_sent }}
|
||||
</td>
|
||||
<td>
|
||||
<img src="{{ solution.language.logo.url }}" width="30px" height="30px">
|
||||
{{ solution.language }}
|
||||
</td>
|
||||
<td>
|
||||
<h4>
|
||||
<span class="badge badge-{% if solution.result == in_queue_status %}secondary{% else %}{% if solution.result == ok_status %}success{% else %}{% if solution.result == testing_status %}info{% else %}danger{% endif %}{% endif %}{% endif %}">{% if solution.result == testing_status %}<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="circle-notch" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="width: 20px;" class="svg-inline--fa fa-circle-notch fa-w-16 fa-spin fa-lg"><path fill="currentColor" d="M288 39.056v16.659c0 10.804 7.281 20.159 17.686 23.066C383.204 100.434 440 171.518 440 256c0 101.689-82.295 184-184 184-101.689 0-184-82.295-184-184 0-84.47 56.786-155.564 134.312-177.219C216.719 75.874 224 66.517 224 55.712V39.064c0-15.709-14.834-27.153-30.046-23.234C86.603 43.482 7.394 141.206 8.003 257.332c.72 137.052 111.477 246.956 248.531 246.667C393.255 503.711 504 392.788 504 256c0-115.633-79.14-212.779-186.211-240.236C302.678 11.889 288 23.456 288 39.056z" class=""></path></svg> {% endif %}{{ solution.result }}</span>
|
||||
</h4>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
@@ -1,85 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Режим Бога{% endblock %}
|
||||
{% block content %}
|
||||
<h1>Настройки системы</h1>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Параметр</th>
|
||||
<th scope="col">Значение</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for param in params %}
|
||||
<tr>
|
||||
<td>{{ param.key }}</td>
|
||||
<td><input style="width: 100%;" name="{{ param.key }}" value="{{ param.value }}"></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-dark" value="Сохранить">
|
||||
</form>
|
||||
<hr>
|
||||
<h1>Курсы</h1>
|
||||
<table border="1px solid black">
|
||||
<tr>
|
||||
<td>
|
||||
<b>id</b>
|
||||
</td>
|
||||
<td>
|
||||
Название
|
||||
</td>
|
||||
<td>
|
||||
Преподаватели
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<input type="text" name="course_name">
|
||||
</td>
|
||||
<td>
|
||||
<select name="teacher">
|
||||
{% for teacher in teachers %}
|
||||
<option value="{{ teacher.email }}">{{ teacher.email }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<input class="btn btn-dark" type="submit" value="Создать">
|
||||
</td>
|
||||
</tr>
|
||||
</form>
|
||||
{% for course in courses %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ course.id }}
|
||||
</td>
|
||||
<td>
|
||||
{{ course.name }}
|
||||
</td>
|
||||
<td>
|
||||
{% for teacher in course.teachers %}
|
||||
{{ teacher.surname }} {{ teacher.name }} {{ teacher.middle_name }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<hr>
|
||||
<button class="btn btn-dark" onclick="window.location.href='/admin/'">Django admin</button>
|
||||
<hr>
|
||||
{% endblock %}
|
@@ -1,290 +1,105 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}{{ task.name }}{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block onload %}doPoll(){% endblock %}
|
||||
|
||||
{% block links %}
|
||||
<script>
|
||||
var current_solution = null;
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% extends 'base_main.html' %}
|
||||
|
||||
{% block scripts %}
|
||||
function partyhard() {
|
||||
var elem = document.getElementById('paint');
|
||||
elem.hidden = false;
|
||||
}
|
||||
function uploaded() {
|
||||
document.getElementById('is_uploaded').style.display = 'block';
|
||||
document.getElementById('is_uploaded').nodeValue = document.getElementById('file-upload').nodeValue;
|
||||
function change(num) {
|
||||
inp = document.getElementById('soltype');
|
||||
if (inp.value == num) return;
|
||||
document.getElementById('button' + inp.value).classList.remove('btn-dark');
|
||||
document.getElementById('button' + inp.value).classList.add('btn-light');
|
||||
document.getElementById('button' + inp.value).focused = false;
|
||||
document.getElementById('input' + inp.value).hidden = true;
|
||||
inp.value = 1 - inp.value;
|
||||
document.getElementById('button' + inp.value).classList.remove('btn-light');
|
||||
document.getElementById('button' + inp.value).classList.add('btn-dark');
|
||||
document.getElementById('button' + inp.value).focused = false;
|
||||
document.getElementById('input' + inp.value).hidden = false;
|
||||
document.getElementById('chosen').hidden = true;
|
||||
document.getElementById('file-upload').value = null;
|
||||
document.getElementById('input0').value = "";
|
||||
}
|
||||
function doPoll() {
|
||||
jQuery.get('/solutions_table?id={{ task.id }}', function(data) {
|
||||
jQuery.get('/solutions_table?task_id={{ task.id }}', function(data) {
|
||||
if (data == 'done') {
|
||||
return
|
||||
}
|
||||
else {
|
||||
document.getElementById('solutions').innerHTML = data;
|
||||
if (current_solution != null) {
|
||||
{% if can_edit %}
|
||||
document.getElementById('log').innerHTML = document.getElementById('log_' + current_solution).innerHTML;
|
||||
{% endif %}
|
||||
document.getElementById('details').innerHTML = document.getElementById('details_' + current_solution).innerHTML;
|
||||
}
|
||||
setTimeout(function() {doPoll()}, 2000);
|
||||
}
|
||||
})
|
||||
jQuery.get('/solutions_table?id={{ task.id }}&render=true', function(data) {
|
||||
jQuery.get('/solutions_table?task_id={{ task.id }}&render=true', function(data) {
|
||||
document.getElementById('solutions').innerHTML = data;
|
||||
if (current_solution != null) {
|
||||
{% if can_edit %}
|
||||
document.getElementById('log').innerHTML = document.getElementById('log_' + current_solution).innerHTML;
|
||||
{% endif %}
|
||||
document.getElementById('details').innerHTML = document.getElementById('details_' + current_solution).innerHTML;
|
||||
}
|
||||
})
|
||||
}
|
||||
{% if can_edit %}
|
||||
function showHideTests(id) {
|
||||
var text = document.getElementById('tests_text_' + id);
|
||||
var button = document.getElementById('tests_button_' + id);
|
||||
text.hidden = !text.hidden;
|
||||
if (text.hidden) {
|
||||
button.textContent = 'Показать тесты';
|
||||
} else {
|
||||
button.textContent = 'Скрыть тесты';
|
||||
}
|
||||
}
|
||||
function showHideLog(id) {
|
||||
var text = document.getElementById('log_text_' + id);
|
||||
var button = document.getElementById('log_button_' + id);
|
||||
text.hidden = !text.hidden;
|
||||
if (text.hidden) {
|
||||
button.textContent = 'Показать лог';
|
||||
} else {
|
||||
button.textContent = 'Скрыть лог';
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
{% if task.show_details or can_edit %}
|
||||
function showData(id) {
|
||||
current_solution = id;
|
||||
const dataTypes = ['details'{% if can_edit %}, 'tests', 'log'{% endif %}];
|
||||
for (const dt of dataTypes) {
|
||||
document.getElementById(dt).innerHTML = document.getElementById(dt + '_' + id).innerHTML;
|
||||
}
|
||||
document.getElementById('resultModalLongTitle').innerHTML = 'Подробная информация о тестировании ' + id;
|
||||
}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!--
|
||||
Помогите! Меня взяли в заложники и заставляют писать на Python!!!
|
||||
Я уже пятый день сижу в подвале и прикручиваю Docker, избавьте меня от мучений и спасите!
|
||||
-->
|
||||
<h5>
|
||||
<a href="/block?id={{ task.block.id }}">Обратно к блоку</a>
|
||||
</h5>
|
||||
<h2>
|
||||
{{ task.name }}
|
||||
{% if can_edit %}
|
||||
<a style="color: black;" href="/admin/task?id={{ task.id }}"><i class="fa fa-pencil"></i></a>
|
||||
{% endif %}
|
||||
<a style="color: black;" href="" data-toggle="modal" data-target="#messageModal"><!--i class="fa fa-comment"></i--></a>
|
||||
</h2>
|
||||
<div class="modal fade" id="messageModal" tabindex="-1" role="dialog" aria-labelledby="messageModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="messageModalLabel">Написать сообщение преподавателям</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="modal-body">
|
||||
<textarea name="message" rows="10" cols="50" style="resize: none;"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
|
||||
<button type="submit" class="btn btn-primary">Отправить</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-9">
|
||||
<h3>Легенда</h3>
|
||||
{% autoescape off %}
|
||||
{{ task.legend }}
|
||||
{% endautoescape %}
|
||||
<hr>
|
||||
<h3>Формат входных данных</h3>
|
||||
{% autoescape off %}
|
||||
{% block onload %}doPoll(){% endblock %}
|
||||
|
||||
{{ task.input }}
|
||||
{% endautoescape %}
|
||||
|
||||
<hr>
|
||||
<h3>Формат выходных данных</h3>
|
||||
{% autoescape off %}
|
||||
|
||||
{{ task.output }}
|
||||
{% endautoescape %}
|
||||
|
||||
<hr>
|
||||
<h3>Спецификации</h3>
|
||||
{% autoescape off %}
|
||||
|
||||
{{ task.specifications }}
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
<div class="col-2">
|
||||
<h5>Таски</h5>
|
||||
<table>
|
||||
{% for t in task.block.tasks %}
|
||||
<tr>
|
||||
{% with mark=t|mark_for_task:user %}
|
||||
{% if mark|marked %}
|
||||
<td>
|
||||
<div style="margin-left: 20px; border: 1px solid black; background: {{ mark|mark_color }}; width: 25px; text-align: center;">
|
||||
{{ mark }}
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<td>
|
||||
<a href="/task?id={{ t.id }}">{% if t.id == task.id %}<b>{{ t.name }}</b>{% else %}{{ t.name }}{% endif %}</a><br>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<h3>Самплы</h3>
|
||||
{% for sample in task.samples %}
|
||||
<h5>Пример {{ sample.input.num }}</h5><br>
|
||||
<b>
|
||||
<table style="width: 100%">
|
||||
<tr>
|
||||
<td>
|
||||
Входные данные
|
||||
</td>
|
||||
<td>
|
||||
Выходные данные
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</b>
|
||||
<hr>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td style="width: 50%; vertical-align: top;">
|
||||
<pre>
|
||||
{{ sample.input.text }}
|
||||
</pre>
|
||||
</td>
|
||||
<td style="width: 50%; vertical-align: top;">
|
||||
<pre>
|
||||
{{ sample.output.text }}
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
{% if can_send or can_edit %}
|
||||
<h2>Отправить решение</h2>
|
||||
<form action="" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<label for="file-upload" class="btn btn-dark" style="margin-top: 20px;">
|
||||
<i class="fa fa-upload"></i> Загрузить файл
|
||||
</label>
|
||||
<span id="is_uploaded" style="display: none;">Решение загружено</span>
|
||||
<input type="file" class="btn form-control-file" id="file-upload" value="Выбрать файл" name="file" onchange="uploaded()">
|
||||
<br><button type="submit" value="Отправить" class="btn btn-outline-dark"><i class="fa fa-share"></i> Отправить</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if not can_edit and can_send %}
|
||||
Осталось попыток: {{ user|last_attempts:task }}
|
||||
{% endif %}
|
||||
|
||||
{% if can_edit or task.show_details %}
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="resultModalLong" tabindex="-1" role="dialog" aria-labelledby="resultModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="resultModalLongTitle">Подробная информация о тестировании</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{% block main %}
|
||||
<h2>{{ task.name }}</h2>
|
||||
{% if task.legend %}
|
||||
<h4>Легенда</h4>
|
||||
{% autoescape off %}
|
||||
<div id="details"></div>
|
||||
{{ task.legend }}
|
||||
{% endautoescape %}
|
||||
{% if can_edit %}
|
||||
<hr>
|
||||
<pre id="tests_text_{{ solution.id }}" hidden>
|
||||
<h4>Тесты</h4><br>
|
||||
<div id="tests"></div>
|
||||
</pre>
|
||||
{% endif %}
|
||||
{% if task.input_format %}
|
||||
<h4>Формат входных данных</h4>
|
||||
{% autoescape off %}
|
||||
{{ task.input_format }}
|
||||
{% endautoescape %}
|
||||
<hr>
|
||||
<pre id="log_text_{{ solution.id }}" hidden>
|
||||
<h4>Лог</h4><br>
|
||||
<div id="log"></div>
|
||||
</pre>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{% if can_edit %}
|
||||
<button type="button" id="log_button_{{ solution.id }}" class="btn btn-warning" onclick="showHideLog('{{ solution.id }}')">Показать лог</button>
|
||||
<button type="button" id="tests_button_{{ solution.id }}" class="btn btn-primary" onclick="showHideTests('{{ solution.id }}')">Показать тесты</button>
|
||||
{% endif %}
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if task.output_format %}
|
||||
<h4>Формат выходных данных</h4>
|
||||
{% autoescape off %}
|
||||
{{ task.output_format }}
|
||||
{% endautoescape %}
|
||||
<hr>
|
||||
{% endif %}
|
||||
<h2 style="margin-top: 20px;">Решения</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">id</th>
|
||||
<th scope="col">Дата и время отправки</th>
|
||||
<th scope="col">Результат</th>
|
||||
<th scope="col">Оценка</th>
|
||||
<th scope="col">Комментарий</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="solutions">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<iframe id="paint" src="https://jspaint.app/" style="width: 100%; height: 1000px;" hidden></iframe>
|
||||
{% if task.specifications %}
|
||||
<h4>Примечания</h4>
|
||||
{% autoescape off %}
|
||||
{{ task.specifications }}
|
||||
{% endautoescape %}
|
||||
<hr>
|
||||
{% endif %}
|
||||
<h2>Отправить решение</h2>
|
||||
<table style="margin-bottom: 10px;">
|
||||
<tr>
|
||||
<input type="hidden" form="solform" name="action" id="soltype" value="0">
|
||||
<td><button class="btn btn-dark" id="button0" onclick="change('0')">Текст</button></td>
|
||||
<td><button class="btn btn-light" id="button1" onclick="change('1')">Файл</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
<form method="POST" enctype="multipart/form-data" id="solform">
|
||||
{% csrf_token %}
|
||||
<select name="language" style="margin-bottom: 30px; width: 10%;">
|
||||
<option disabled>Выберите язык</option>
|
||||
{% for lang in languages %}
|
||||
<option value="{{ lang.id }}">{{ lang }}</option>
|
||||
{% endfor %}
|
||||
</select><br>
|
||||
<textarea id="input0" style="width: 1000px; height: 400px; resize: none;" name="code" placeholder="Вставьте сюда свой код"></textarea>
|
||||
<label for="file-upload" class="btn btn-outline-dark" id="input1" hidden>
|
||||
<i class="fa fa-upload"></i> Загрузить файл
|
||||
</label>
|
||||
<p id="chosen" hidden>Файл выбран</p>
|
||||
<input type="file" style="display: none;" onchange="document.getElementById('chosen').hidden = false;" class="btn form-control-file" id="file-upload" value="Выбрать файл" name="file">
|
||||
<br><button type="submit" style="margin-top: 30px; margin-bottom: 30px;" class="btn btn-dark">Отправить</button>
|
||||
</form>
|
||||
<hr>
|
||||
<h2>Решения</h2>
|
||||
<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>
|
||||
</thead>
|
||||
<tbody id="solutions">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
@@ -1,327 +1,150 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends 'base_main.html' %}
|
||||
|
||||
{% load filters %}
|
||||
|
||||
{% block title %}{{ task.name }}|настройки{% endblock %}
|
||||
{% block title %}{{ task.name }}{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function uploaded() {
|
||||
document.getElementById('is_uploaded').style.display = 'block';
|
||||
document.getElementById('is_uploaded').nodeValue = document.getElementById('file-upload').nodeValue;
|
||||
}
|
||||
function uploaded1() {
|
||||
document.getElementById('send').style.display = 'block';
|
||||
document.getElementById('is_uploaded1').nodeValue = document.getElementById('file-upload1').nodeValue;
|
||||
}
|
||||
function valueChanged() {
|
||||
const other = document.getElementById('show_details');
|
||||
other.disabled = !document.getElementById('show_result').checked;
|
||||
console.log('changed');
|
||||
if (other.disabled) {
|
||||
other.checked = false;
|
||||
function deleteFile(file_id) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/admin/task?task_id={{ task.id }}",
|
||||
data: {"id": file_id, "csrfmiddlewaretoken": document.getElementsByName("csrfmiddlewaretoken")[0].value, "action": "delete_file"},
|
||||
success: function(data) {
|
||||
if (data == "ok") {
|
||||
var elem = document.getElementById("file_" + file_id);
|
||||
elem.parentNode.removeChild(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
function set_checkboxes() {
|
||||
if (!document.getElementById('show_result').checked) {
|
||||
document.getElementById('show_details').disabled = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function setActionCreate(action) {
|
||||
document.getElementById('action_create').value = action;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block onload %}set_checkboxes(){% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
input[name="new_file"] {
|
||||
display: none;
|
||||
}
|
||||
.my_td {
|
||||
vertical-align: middle;
|
||||
height: 20px;
|
||||
}
|
||||
.params {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.in {
|
||||
width: 500%;
|
||||
}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h5><a href="/admin/block?id={{ task.block.id }}">{{ task.block.name }}</a></h5>
|
||||
<h2>{{ task.name }} <a style="color: black;" href="/task?id={{ task.id }}"><i class="fa fa-eye"></i></a></h2>
|
||||
<form action="" method="POST" id="main_form" enctype="multipart/form-data">
|
||||
{% block main %}
|
||||
<h3 style="margin-bottom: 40px;">Настройки задачи</h3>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td style="width: 250px;">
|
||||
Название задачи
|
||||
</td>
|
||||
<td>
|
||||
<h4><input type="text" value="{{ task.name }}" name="name" class="task-settings-input" placeholder="Новая задача"></h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Легенда
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="task-settings-input task-settings-textarea" name="legend">{{ task.legend }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Формат входных данных
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="task-settings-input task-settings-textarea" name="input_format">{{ task.input_format }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Формат выходных данных
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="task-settings-input task-settings-textarea" name="output_format">{{ task.output_format }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Примечания
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="task-settings-input task-settings-textarea" name="specifications">{{ task.specifications }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Ограничение по времени (мс)
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="time_limit" value="{{ task.time_limit }}" class="task-settings-input">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="submit" class="btn btn-light" style="margin-top: 15px;"><i class="fa fa-save"></i> Сохранить</button>
|
||||
</form>
|
||||
<hr><hr>
|
||||
<h3 style="margin-bottom: 40px;">Загрузка тестов и файлов</h3>
|
||||
<p style="color: red">{{ error_message }}</p>
|
||||
<table style="width: 80%;">
|
||||
<tr>
|
||||
<td>
|
||||
<h4>Тесты</h4>
|
||||
</td>
|
||||
<td>
|
||||
<h4>Файлы</h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{% for test in task.tests %}
|
||||
<div id="file_{{ test.id }}">
|
||||
<i class="fa fa-file"></i> <button class="btn btn-link" {% if not test.readable %}style="color: red;"{% endif %}>{{ test.filename }}</button><button class="btn btn-link" style="color: black;" onclick="deleteFile({{ test.id }});"><i class="fa fa-times"></i> </button><br>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<input type="file" style="display: none;" form="form_test_upload" onchange="this.form.submit();" class="btn form-control-file" id="test-upload" value="Выбрать файл" name="file">
|
||||
<label for="test-upload" class="btn btn-primary"><i class="fa fa-upload"></i> Загрузить тесты</label><button style="margin-left: 10px; margin-top: -8px;" class="btn btn-success" data-toggle="modal" data-target="#exampleModalLongnewtest" onclick="setActionCreate('create_test');"><i class="fa fa-plus"></i></button>
|
||||
<form method="POST" enctype="multipart/form-data" id="form_test_upload">
|
||||
<input name="action" type="hidden" value="test_upload">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
{% for file in task.files %}
|
||||
<div id="file_{{ file.id }}">
|
||||
<i class="fa fa-file"></i> <button class="btn btn-link" {% if not file.readable %}style="color: red;"{% endif %}>{{ file.filename }}</button><button class="btn btn-link" style="color: black;" onclick="deleteFile({{ file.id }});"><i class="fa fa-times"></i> </button><br>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<input type="file" style="display: none;" form="form_file_upload" onchange="this.form.submit();" class="btn form-control-file" id="file-upload" value="Выбрать файл" name="file">
|
||||
<label for="file-upload" class="btn btn-primary"><i class="fa fa-upload"></i> Загрузить файлы</label><button style="margin-left: 10px; margin-top: -8px;" class="btn btn-success" data-toggle="modal" data-target="#exampleModalLongnewtest" onclick="setActionCreate('create_file');"><i class="fa fa-plus"></i></button>
|
||||
<form method="POST" enctype="multipart/form-data" id="form_file_upload">
|
||||
<input name="action" type="hidden" value="file_upload">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr class="params">
|
||||
<td>
|
||||
Легенда
|
||||
</td>
|
||||
<td>
|
||||
<textarea form="main_form" rows="15" class="in" style="resize: none;" name="legend">{{ task.legend }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="params">
|
||||
<td>
|
||||
Формат входных данных
|
||||
</td>
|
||||
<td>
|
||||
<textarea form="main_form" rows="15" class="in" style="resize: none;" name="input">{{ task.input }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="params">
|
||||
<td>
|
||||
Формат выходных данных
|
||||
</td>
|
||||
<td>
|
||||
<textarea form="main_form" rows="15" class="in" style="resize: none;" name="output">{{ task.output }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="params">
|
||||
<td>
|
||||
Спецификации
|
||||
</td>
|
||||
<td>
|
||||
<textarea form="main_form" rows="15" class="in" style="resize: none;" name="specifications">{{ task.specifications }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Ограничения по времени
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="text" name="time_limit" class="in" value="{{ task.time_limit }}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Вес задачи
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="text" name="weight" class="in" value="{{ task.weight }}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Максимальная оценка
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="text" name="max_mark" class="in" value="{{ task.max_mark }}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Максимум решений
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="text" name="max_solutions_count" class="in" value="{{ task.max_solutions_count }}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Формула оценки
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="text" name="mark_formula" class="in" value="{{ task.mark_formula }}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Сдается полное решение
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="checkbox" name="full_solution" {{ task.is_full_solution }}>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Показывать результат тестирования
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="checkbox" id="show_result" name="show_result" onchange="valueChanged()" {% if task.show_result %}checked{% endif %}>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Показывать детали тестирования
|
||||
</td>
|
||||
<td>
|
||||
<input form="main_form" type="checkbox" id="show_details" name="show_details" {{ task.showable }}>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Приоритет
|
||||
</td>
|
||||
<td>
|
||||
<select name="priority">
|
||||
{% for i in 10|num_range %}
|
||||
<option {% if task.priority == i %}selected{% endif %}>{{ i }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
Тесты
|
||||
</td>
|
||||
<td>
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-link" data-toggle="modal" data-target="#exampleModalLong">
|
||||
Посмотреть
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade bd-example-modal-lg" id="exampleModalLong" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitle">Unit тесты</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<textarea cols="82" rows="30" name="tests_text">{{ task.tests_text }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fa fa-times"></i> Close</button>
|
||||
<button type="submit" class="btn btn-primary" name="ACTION" value="SAVE_TESTS"><i class="fa fa-save"></i> Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="exampleModalLongnewtest" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitlenewtest" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitlenewtest">Создать новый файл</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<input type="text" placeholder="Имя файла" name="newfile_name">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td style="vertical-align: top; padding-top: 10px;">
|
||||
Дополнительные файлы и самплы
|
||||
</td>
|
||||
<td style="vertical-align: top;">
|
||||
<table>
|
||||
{% for file in task.files %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if file.can_be_sample %}
|
||||
<input form="main_form" type="checkbox" name="sample_{{ file.id }}" {{ file.is_sample }}>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<button type="submit" class="close" name="ACTION" value="DELETE_FILE_{{ file.id }}">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<img width="14px" height="14px" src="https://image.flaticon.com/icons/svg/876/876755.svg">
|
||||
</td>
|
||||
<td>
|
||||
{% if file.readable %}
|
||||
<button type="button" class="btn btn-link" data-toggle="modal" data-target="#filesModalLong{{ file.id }}">
|
||||
{{ file.filename }}
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade bd-example-modal-lg" id="filesModalLong{{ file.id }}" tabindex="-1" role="dialog" aria-labelledby="filesModalLongTitle{{ file.id }}" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="filesModalLongTitle{{ file.id }}">{{ file.filename }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<textarea cols="82" rows="30" name="extra_file_text_{{ file.id }}">{{ file.text }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
Файл для компиляции <input type="checkbox" name="{{ file.id }}_for_compilation" {{ file.is_for_compilation }}>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fa fa-times"></i> Close</button>
|
||||
<button type="submit" class="btn btn-primary" name="ACTION" value="SAVE_EXTRA_FILE_{{ file.id }}"><i class="fa fa-save"></i> Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-link" style="color: red;">
|
||||
{{ file.filename }}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<label for="files" class="btn btn-primary">
|
||||
<i class="fa fa-upload"></i> Загрузить файл
|
||||
</label>
|
||||
<form method="POST">
|
||||
<input type="file" class="btn form-control-file" id="files" value="Выбрать файл" name="file" onchange="uploaded1()">
|
||||
</form>
|
||||
<label for="add_file" class="btn btn-success">
|
||||
<i class="fa fa-plus"></i>
|
||||
</label>
|
||||
<input type="button" class="btn btn-success" id="add_file" value="Создать файл" name="new_file" data-toggle="modal" data-target="#exampleModalLongnewfile">
|
||||
<button name="ACTION" value="UPLOAD_EXTRA_FILE" type="submit" class="btn btn-success" style="display: none;" id="send">Отправить</button>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="modal fade" id="exampleModalLongnewfile" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitlenewfile" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitlenewfile">Создать новый файл</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<input type="text" placeholder="Имя файла" name="newfile_name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fa fa-times"></i> Закрыть</button>
|
||||
<button name="ACTION" value="CREATE_EXTRA_FILE" type="submit" class="btn btn-primary"><i class="fa fa-file"></i> Создать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<button type="submit" name="ACTION" value="SAVE" class="btn btn-dark"><i class="fa fa-save"></i> Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-times"></i> Закрыть</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-file"></i> Создать</button>
|
||||
<input id="action_create" type="hidden" name="action" value="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% if is_superuser %}
|
||||
<form style="margin-top: 15px;" id="another_form" method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="ACTION" value="DELETE" form="another_form">
|
||||
<button form="another_form" type="button" onclick="let del = confirm('Данное действие приведет к удалению условия, тестов, дополнительных файлов и решений, привязанных к этому таску. Точно удаляем?'); if (del) {this.form.submit();}" class="btn btn-dark"><i class="fa fa-trash"></i> Удалить таск</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
49
templates/tasks.html
Normal file
49
templates/tasks.html
Normal file
@@ -0,0 +1,49 @@
|
||||
{% extends 'base_main.html' %}
|
||||
|
||||
{% block title %}Задачи{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Задачи</h2>
|
||||
</td>
|
||||
{% if user.userinfo.can_create %}
|
||||
<td>
|
||||
<button style="margin-left: 20px;" class="btn btn-success" data-toggle="modal" data-target="#example"><i class="fa fa-plus"></i></button>
|
||||
<div class="modal fade" id="example" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form method="POST">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitle">Создать новую задачу</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{% csrf_token %}
|
||||
<input type="text" name="name" placeholder="Название задачи">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-times-circle"></i> Закрыть</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-plus-circle"></i> Создать</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
{% for task in user.userinfo.available_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>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
@@ -1,165 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}{{ course.name }}|настройки{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function uploaded() {
|
||||
document.getElementById('is_uploaded').style.display = 'block';
|
||||
document.getElementById('is_uploaded').nodeValue = document.getElementById('file-upload').nodeValue;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{{ course.name }}</h3>
|
||||
<h5>Добавить участников</h5>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<input name="input" type="text" placeholder="ФИО, почта или группа" style="width: 200px;">
|
||||
</td>
|
||||
<td>
|
||||
<input type="submit" value="Добавить" class="btn btn-dark">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<form action="" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<label for="file-upload" class="btn btn-dark" style="margin-top: 20px;">
|
||||
Загрузить файл
|
||||
</label>
|
||||
<span id="is_uploaded" style="display: none;">Файл загружен</span>
|
||||
<input type="file" class="btn form-control-file" id="file-upload" value="Выбрать файл" name="file" onchange="uploaded()">
|
||||
<br><input type="submit" value="Отправить" class="btn btn-outline-dark">
|
||||
</form>
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#example" style="margin-top: 20px;">
|
||||
Правила загрузки файла
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="example" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitle">Инструкция к загружаемому файлу</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<pre>
|
||||
Загружаемый файл должен представлять из себя
|
||||
JSON файл, составленый следующим образом:
|
||||
[
|
||||
{
|
||||
"email": "samplename@samplemail.com",
|
||||
"surname": "Иванов",
|
||||
"name": "Иван",
|
||||
"middle_name": "Иванович",
|
||||
"group": "БПИ183"
|
||||
},
|
||||
{
|
||||
"email": "samplename2@samplemail.com",
|
||||
"surname": "Чуйкин",
|
||||
"name": "Виктор",
|
||||
"middle_name": "Вениаминович",
|
||||
"group": "БПИ9000"
|
||||
}
|
||||
]
|
||||
|
||||
Пояснения к заполняемым полям:
|
||||
email - почта
|
||||
surname - фамилия
|
||||
name - имя
|
||||
middle_name - отчество
|
||||
group - группа
|
||||
|
||||
Все пользователи будут зарегестрированы на сервисе,
|
||||
и каждому из них на указанные почты будут
|
||||
отправлены сгенерированные пароли.
|
||||
Также каждый пользователь будет подписан на
|
||||
данный курс. Если пользователь уже был
|
||||
зарегестрирован в системе, запись о нем
|
||||
будет проигнорирована.
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Понял(-а)</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<h1>Участники</h1>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Фамилия</th>
|
||||
<th scope="col">Имя</th>
|
||||
<th scope="col">Отчество</th>
|
||||
<th scope="col">Группа</th>
|
||||
<th scope="col">Почта</th>
|
||||
<th scope="col">Роль</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in course.subscribes %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ user.userinfo.surname }}
|
||||
</td>
|
||||
<td>
|
||||
{{ user.userinfo.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ user.userinfo.middle_name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ user.userinfo.group }}
|
||||
</td>
|
||||
<td>
|
||||
{{ user.userinfo.user.email }}
|
||||
</td>
|
||||
<td>
|
||||
{% with role=user.role %}
|
||||
{% if role == 'Студент' or role == 'Ассистент' %}
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<select name="role_{{ user.userinfo.user.email }}" onchange="this.form.submit();">
|
||||
<option {% if role == 'Студент' %}selected{% endif %}>Студент</option>
|
||||
<option {% if role == 'Ассистент' %}selected{% endif %}>Ассистент</option>
|
||||
</select>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ user.role }}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>
|
||||
<form method="POST" onsubmit="return confirm('Точно отписываем?');">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="user_delete" value="{{ user.userinfo.user.email }}">
|
||||
<input type="submit" value="Отписка" class="btn btn-outline-danger">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user