- Lab page is now read-only with a settings screen for levels/variants; variant issuance moved to a large modal on the group page (assign-fragment). - Header: bordeaux logo and 2px accent underline, bordeaux login/logout/theme buttons; smaller radii across the UI; filled secondary/danger buttons. - Includes prior agent work (login backoff, no-cache pages, API timeouts, content tweaks) and fixes (variant usage Map.values, import order). - Bump static asset version to v=9.
65 lines
4.0 KiB
HTML
65 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru" xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/base :: layout(~{::title}, ~{::#content})}">
|
||
<head><title>Группы — LMS</title></head>
|
||
<body>
|
||
<div id="content">
|
||
<div class="flex flex-wrap items-center justify-between gap-4 mb-6">
|
||
<h1 class="page-title m-0">Группы</h1>
|
||
<div class="flex gap-2">
|
||
<input class="input table-search" data-target="groups-table"
|
||
placeholder="Поиск по названию…" aria-label="Поиск по группам">
|
||
<button class="btn btn-secondary" type="button" onclick="openModal('modal-import-group')">Импорт</button>
|
||
<button class="btn btn-primary" type="button" onclick="openModal('modal-create-group')">+ Новая группа</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card card-flush">
|
||
<table id="groups-table" class="tablekit">
|
||
<thead><tr><th class="th-sortable is-asc" title="Название — по возрастанию">Название</th><th>Студентов</th><th data-nosort>Пароли</th></tr></thead>
|
||
<tbody>
|
||
<tr th:each="group : ${groups}">
|
||
<td><a th:href="@{/admin/groups/{id}(id=${group.id})}" th:text="${group.name}">—</a></td>
|
||
<td th:text="${group.studentCount}">0</td>
|
||
<td><a th:href="@{/admin/groups/{id}/credentials(id=${group.id}, format='xlsx')}">XLSX</a><span class="nav-sep ml-2">·</span><a class="ml-2" th:href="@{/admin/groups/{id}/credentials(id=${group.id}, format='csv')}">CSV</a></td>
|
||
</tr>
|
||
<tr th:if="${#lists.isEmpty(groups)}"><td colspan="3" class="empty">Групп пока нет.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<dialog id="modal-create-group" class="modal">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title">Новая группа</h2>
|
||
<button class="modal-close" type="button" aria-label="Закрыть" onclick="closeModal('modal-create-group')">✕</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form class="form-stack" th:action="@{/admin/groups}" method="post">
|
||
<div><label class="label" for="name">Название</label>
|
||
<input class="input" id="name" name="name" placeholder="ПИ-11БО" required autofocus></div>
|
||
<button class="btn btn-primary" type="submit">Создать</button>
|
||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||
</form>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="modal-import-group" class="modal">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title">Импорт студентов</h2>
|
||
<button class="modal-close" type="button" aria-label="Закрыть" onclick="closeModal('modal-import-group')">✕</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form class="form-stack" th:action="@{/admin/groups/import}" method="post" enctype="multipart/form-data">
|
||
<p class="text-sm text-muted">Файл .xls, .xlsx или .csv со столбцами: студенческий номер, ФИО, основа обучения. Логин — студенческий номер, пароль сгенерируется и покажется после импорта.</p>
|
||
<div><label class="label" for="file">Файл со списком</label>
|
||
<input class="input" id="file" name="file" type="file" accept=".xls,.xlsx,.csv" required autofocus></div>
|
||
<div><label class="label" for="groupName">Название группы (необязательно)</label>
|
||
<input class="input" id="groupName" name="name" placeholder="Возьмём из файла"></div>
|
||
<button class="btn btn-primary" type="submit">Импортировать</button>
|
||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||
</form>
|
||
</div>
|
||
</dialog>
|
||
</div>
|
||
</body>
|
||
</html>
|