Files
LMS/web/src/main/resources/templates/student/lab.html

114 lines
7.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru" xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/base :: layout(~{::title}, ~{::#content})}">
<head><title th:text="|ЛР ${lab.number} — LMS|">Лабораторная</title></head>
<body>
<div id="content">
<a th:href="@{/student/labs}" class="nav-link">← Лабораторные</a>
<div class="flex flex-wrap items-center justify-between gap-4 mt-4 mb-2">
<h1 class="page-title mb-1" th:text="|Лабораторная работа ${lab.number}. ${lab.title}|">ЛР</h1>
</div>
<p class="text-muted mb-6">
<span th:if="${deadlineMsk}"><b>Срок сдачи кода:</b> <span th:text="${deadlineMsk}"></span> МСК</span>
<span th:if="${deadlineMsk != null and defenseMsk != null}" class="nav-sep">·</span>
<span th:if="${defenseMsk}"><b>Защита:</b> <span th:text="${deadlineMsk}"></span> МСК</span>
</p>
<h2 class="section-title">Условие лабораторной</h2>
<div class="card card-body md-body mb-6" th:utext="${descriptionHtml}"></div>
<th:block th:if="${assignment != null}">
<h2 class="section-title">Ваш вариант <span class="font-mono" th:text="${assignment.variantNumber}"></span>
<span class="text-muted text-sm" th:if="${assignment.levelTitle}" th:text="|(${assignment.levelTitle})|"></span></h2>
<div class="card card-body md-body mb-6" th:utext="${statementHtml}"></div>
</th:block>
<div th:if="${assignment == null}" class="card card-body mb-6">
<p class="text-muted">Ваш вариант ещё не распределён. Дождитесь, пока преподаватель распределит варианты.</p>
</div>
<h2 class="section-title">Сдача работы</h2>
<div class="card form-card form-stack mb-4">
<p class="text-sm text-muted" th:if="${!canSubmit}">Приём решений закрыт. Вы по-прежнему можете скачать отправленные работы ниже.</p>
<form th:if="${canSubmit}" th:action="@{/student/labs/{id}/submit(id=${lab.id})}" method="post" enctype="multipart/form-data" class="form-stack">
<input type="hidden" name="_csrf" th:value="${csrfToken}">
<p class="text-sm text-muted">zip‑архив или исходники (.c/.h). Можно пересдавать сколько угодно раз до истечения срока — засчитывается последняя попытка.</p>
<div><input class="input" name="files" type="file" multiple required></div>
<button class="btn btn-primary" type="submit">Отправить решение</button>
</form>
<div th:if="${canSubmit and #lists.isEmpty(submissions)}" class="text-muted text-sm">Вы ещё ничего не сдавали.</div>
</div>
<h3 class="group-title">История сдач</h3>
<div class="card card-flush mb-6">
<table>
<thead><tr><th>Попытка</th><th>Время (МСК)</th><th>Файлы</th><th></th></tr></thead>
<tbody>
<tr th:each="s : ${submissions}">
<td th:text="${s.seq}">1</td>
<td class="text-muted" th:text="${s.createdAt}"></td>
<td class="font-mono text-sm" th:text="${#strings.listJoin(s.files, ', ')}">main.c</td>
<td><a class="btn btn-secondary" th:href="'/student/submissions/' + ${s.id} + '/download'">Скачать</a></td>
</tr>
<tr th:if="${#lists.isEmpty(submissions)}"><td colspan="4" class="empty">Нет сдач.</td></tr>
</tbody>
</table>
</div>
<th:block th:if="${canSeeGrade}">
<h2 class="section-title">Оценка и комментарии</h2>
<div class="card card-body mb-6">
<p class="mb-4 mt-1">Ваша оценка за лабораторную: <span class="score-big" th:text="${grade}"></span></p>
<div class="review-cols">
<div class="review-col" th:if="${!#lists.isEmpty(commentsPositive)}">
<h3 class="group-title tone-positive-text">Позитивный</h3>
<ul class="review-list"><li th:each="c : ${commentsPositive}" th:text="${c.text}">—</li></ul>
</div>
<div class="review-col" th:if="${!#lists.isEmpty(commentsNegative)}">
<h3 class="group-title tone-negative-text">Негативный</h3>
<ul class="review-list"><li th:each="c : ${commentsNegative}" th:text="${c.text}">—</li></ul>
</div>
<div class="review-col" th:if="${!#lists.isEmpty(commentsNeutral)}">
<h3 class="group-title">Нейтральный</h3>
<ul class="review-list"><li th:each="c : ${commentsNeutral}" th:text="${c.text}">—</li></ul>
</div>
</div>
<p class="text-sm text-muted"
th:if="${#lists.isEmpty(commentsPositive) and #lists.isEmpty(commentsNegative) and #lists.isEmpty(commentsNeutral)}">
Комментариев к оценке нет.
</p>
</div>
</th:block>
<h2 class="section-title">Защита лабораторной</h2>
<div class="card card-body form-stack">
<div th:if="${defense == null}" class="text-muted">
Индивидуальное задание для защиты ещё не назначено. Преподаватель сообщит, когда можно приходить.
</div>
<th:block th:if="${defense != null and defense.status == 'waiting'}">
<p class="text-sm">Преподаватель уже выдал вам одноразовый код. Подойдите на защиту и введите его:</p>
<form class="inline-form" th:action="@{/student/defenses/start}" method="post">
<input type="hidden" name="_csrf" th:value="${csrfToken}">
<input type="hidden" name="labId" th:value="${lab.id}">
<input class="input w-260" name="code" placeholder="6-значный код" maxlength="6" pattern="[0-9]{6}"
inputmode="numeric" autocomplete="one-time-code" required>
<button class="btn btn-primary" type="submit">Приступить</button>
</form>
</th:block>
<div th:if="${defense != null and defense.status == 'started'}">
<p class="text-sm defense-timer" th:attr="data-seconds=${defense.secondsLeft},data-lab=${lab.id}"></p>
<h3 class="group-title">Ваше индивидуальное задание</h3>
<div class="md-body" th:utext="${defense.assignmentHtml}"></div>
<form class="mt-4" th:action="'/student/defenses/' + ${defense.id} + '/finish?labId=' + ${lab.id}" method="post" data-confirm="Завершить защиту? Продолжить её будет нельзя — дождитесь преподавателя.">
<input type="hidden" name="_csrf" th:value="${csrfToken}">
<button class="btn btn-primary" type="submit">Готов к сдаче</button>
</form>
</div>
<div th:if="${defense != null and defense.status == 'ready'}">
<p><span class="badge" th:classappend="${defense.readyReason == 'timeout'} ? 'badge-warn' : 'badge-ok'" th:text="${defense.readyReason == 'timeout' ? 'Вышло время' : 'Готов к сдаче'}"></span></p>
<p class="text-sm text-muted">Ожидайте преподавателя с проверкой.</p>
</div>
</div>
<script th:src="@{/js/defense-timer.js(v='30')}" defer></script>
</div>
</body>
</html>