Files
LMS/web/src/main/resources/templates/teacher/course.html
Vladislav Kopnin 65ed08f5c2 feat(web): перевести браузерные URL курсов на courseNo
- teacher/admin course pages, content, gradebook, profile, downloads
- courseNo -> UUID только на границе REST API
- обновлены e2e, шаблоны, тесты и docs
- LDD-UI-002; baseline 59 claims / 385 тестов
2026-10-29 19:51:03 +03:00

135 lines
7.8 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="${course.title} + ' — LMS'">Курс</title></head>
<body>
<div id="content">
<a th:href="@{/teacher}" class="nav-link">← Мои курсы</a>
<div class="page-head mb-2">
<div>
<h1 class="page-title" th:text="|Курс ${course.courseNo}. ${course.title}|">Курс</h1>
<div class="meta">
<span class="badge"
th:classappend="${course.status == 'ACTIVE' ? 'badge-ok' : 'badge-warn'}"
th:text="${course.status == 'ACTIVE' ? 'активен' : 'в архиве'}">—</span>
<span th:text="|Групп: ${#lists.size(groups)}|">Групп: 0</span>
· <span th:text="|Лабораторных: ${#lists.size(labs)}|">Лабораторных: 0</span>
</div>
<div class="mt-2 flex flex-wrap gap-2">
<a class="btn btn-sm btn-primary" th:href="@{/teacher/courses/{no}/content(no=${course.courseNo})}">Материалы курса</a>
<a class="btn btn-sm btn-secondary" th:href="@{/learn/course/{no}(no=${course.courseNo})}">Учебные материалы курса</a>
</div>
</div>
</div>
<div class="row g-4 mt-4">
<div class="col-lg-6">
<h2 class="section-title">Группы курса</h2>
<div class="card card-flush">
<table>
<thead>
<tr>
<th>Группа</th>
<th>Добавлена</th>
<th th:unless="${currentUser.admin}" data-nosort></th>
</tr>
</thead>
<tbody>
<tr th:each="group : ${groups}">
<td>
<a th:if="${currentUser.admin}"
th:href="@{/admin/groups/{id}(id=${group.groupId})}"
class="font-mono"
th:text="${groupNames[group.groupId] ?: group.groupId}">—</a>
<a th:unless="${currentUser.admin}"
th:href="@{/teacher/courses/{no}/groups/{groupId}(no=${course.courseNo}, groupId=${group.groupId})}"
th:text="${groupNames[group.groupId] ?: group.groupId}">—</a>
</td>
<td class="text-muted" th:text="${group.addedAt}">—</td>
<td th:unless="${currentUser.admin}" class="text-center">
<div class="flex flex-wrap items-center justify-center gap-2">
<a class="btn btn-sm btn-secondary"
th:href="@{/admin/groups/{groupId}(groupId=${group.groupId}, courseNo=${course.courseNo})}">Ведомость</a>
<a class="btn btn-sm btn-secondary"
th:href="@{/teacher/courses/{no}/groups/{groupId}(no=${course.courseNo}, groupId=${group.groupId})}">Студенты</a>
<form class="inline-form"
th:action="@{/teacher/courses/{no}/groups/detach(no=${course.courseNo})}"
method="post" data-confirm="Отвязать группу от курса? Ведомость и данные группы останутся в системе.">
<input type="hidden" name="_csrf" th:value="${csrfToken}">
<input type="hidden" name="groupId" th:value="${group.groupId}">
<button class="btn btn-sm btn-danger" type="submit">Отвязать</button>
</form>
</div>
</td>
</tr>
<tr th:if="${#lists.isEmpty(groups)}">
<td th:attr="colspan=${currentUser.admin ? 2 : 3}" class="empty">К курсу не привязано ни одной группы.</td>
</tr>
</tbody>
</table>
</div>
<form class="card card-body form-stack mt-4" th:unless="${currentUser.admin}"
th:action="@{/teacher/courses/{no}/groups/attach(no=${course.courseNo})}" method="post">
<div><label class="label" for="courseGroup">Привязать группу</label>
<select class="input" id="courseGroup" name="groupId" required
th:disabled="${#lists.isEmpty(availableGroups)}">
<option value="">— выберите группу —</option>
<option th:each="group : ${availableGroups}" th:value="${group.id}"
th:text="${group.name} + (${group.status == 'ACTIVE'} ? '' : ' (архив)')">—</option>
</select>
<p class="hint" th:if="${#lists.isEmpty(availableGroups)}">Все доступные группы уже привязаны.</p>
</div>
<button class="btn btn-primary" type="submit"
th:disabled="${#lists.isEmpty(availableGroups)}">Привязать</button>
<input type="hidden" name="_csrf" th:value="${csrfToken}">
</form>
<p class="hint mt-2" th:if="${currentUser.admin}">Состав групп и привязку к курсу изменяет администратор.</p>
</div>
<div class="col-lg-6">
<h2 class="section-title">Сведения о курсе</h2>
<div class="card card-body">
<p class="text-sm">Создан: <span th:text="${course.createdAt}">—</span></p>
<p class="text-sm">Обновлён: <span th:text="${course.updatedAt}">—</span></p>
<p class="text-sm" th:if="${!#lists.isEmpty(course.teachers)}">
Преподавателей на курсе: <span th:text="${#lists.size(course.teachers)}">0</span>
</p>
</div>
</div>
</div>
<h2 class="section-title mt-8 mb-2">Лабораторные курса</h2>
<div class="card card-flush">
<table>
<thead>
<tr><th>№</th><th>Название</th><th>Статус</th><th>Вариантов</th><th>Срок сдачи</th><th>Защита</th></tr>
</thead>
<tbody>
<tr th:each="lab : ${labs}">
<td th:text="${lab.number}">1</td>
<td>
<a th:if="${currentUser.admin}"
th:href="@{/admin/labs/{id}(id=${lab.id})}"
th:text="${lab.title}">—</a>
<span th:unless="${currentUser.admin}" th:text="${lab.title}">—</span>
</td>
<td>
<span class="badge"
th:classappend="${lab.status == 'published' ? 'badge-ok' : 'badge-warn'}"
th:text="${lab.status == 'published' ? 'Опубликована' : (lab.status == 'archived' ? 'В архиве' : 'Черновик')}">—</span>
</td>
<td th:text="${lab.variantCount}">0</td>
<td class="text-muted" th:text="${lab.deadlineMsk ?: '—'}">—</td>
<td class="text-muted" th:text="${lab.defenseMsk ?: '—'}">—</td>
</tr>
<tr th:if="${#lists.isEmpty(labs)}">
<td colspan="6" class="empty">В курсе пока нет лабораторных.</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>