Tables: initial ФИО order, click-to-sort columns, substring search
- identity group detail (and thus every student list) is ordered by full name; defense rows on the group page sorted by name + lab number - tablekit.js: click a header to sort (numeric-aware, ru locale), second click flips direction (▲/▼ indicator); search input with data-target filters rows by substring live - tables wired: group matrix (with data-sort on variant cells), defense table (data-sort on status/date), students table, lab assignment lists per group, groups list and labs list; name/number columns pre-marked ascending - non-sortable columns marked data-nosort (checkbox/actions)
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-2">
|
||||
<h2 class="section-title m-0">Результаты по лабораторным</h2>
|
||||
<div class="flex flex-wrap items-center gap-2" th:if="${!#lists.isEmpty(labs)}">
|
||||
<input class="input input-sm table-search" data-target="matrix-table"
|
||||
placeholder="Поиск по студенту…" aria-label="Поиск по студенту">
|
||||
<label class="label m-0" for="lab-focus">Показать:</label>
|
||||
<select class="input input-sm" id="lab-focus" onchange="focusLab()">
|
||||
<option value="">все лабораторные</option>
|
||||
@@ -44,10 +46,10 @@
|
||||
<div th:if="${#lists.isEmpty(labs)}" class="card card-body mb-6 text-muted">Опубликованных лабораторных пока нет.</div>
|
||||
<div class="card card-flush mb-6" th:if="${!#lists.isEmpty(labs)}">
|
||||
<div class="scroll-x">
|
||||
<table class="matrix">
|
||||
<table class="matrix tablekit" id="matrix-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="matrix-sticky">Студент</th>
|
||||
<th class="matrix-sticky th-sortable is-asc" title="ФИО — по возрастанию">Студент</th>
|
||||
<th th:each="lab : ${labs}" class="text-center lab-col" th:attr="data-lab=${lab.id}">
|
||||
<div class="lab-col-head">
|
||||
<div class="lab-head-row">
|
||||
@@ -73,7 +75,7 @@
|
||||
<div class="font-medium" th:text="${row.fullName}">—</div>
|
||||
<div class="text-sm text-muted font-mono" th:text="${row.studentNo}">—</div>
|
||||
</td>
|
||||
<td th:each="cell, iterStat : ${row.cells}" class="text-center cell-lab" th:attr="data-lab=${cell.labId}">
|
||||
<td th:each="cell, iterStat : ${row.cells}" class="text-center cell-lab" th:attr="data-lab=${cell.labId},data-sort=${cell.variantNumber}">
|
||||
<div class="cell-chips">
|
||||
<span class="cell-chip"
|
||||
th:title="(${cell.variantNumber} ? 'Вариант ' + ${cell.variantNumber} : 'Вариант') + ' — ' + (${cell.variantManual} ? 'закреплён вручную (раздача его не тронет)' : 'выдан автоматически')">
|
||||
@@ -113,11 +115,13 @@
|
||||
</select>
|
||||
<button class="btn btn-primary btn-sm" type="button" onclick="openDefenseForm(this)">Назначить задание</button>
|
||||
<button class="btn btn-secondary btn-sm" type="button" onclick="openModal('modal-defense-import')">Импорт CSV</button>
|
||||
<input class="input input-sm table-search" data-target="defense-table"
|
||||
placeholder="Поиск по студенту…" aria-label="Поиск по заданиям защиты">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-flush mb-8">
|
||||
<table id="defense-table">
|
||||
<thead><tr><th>Студент</th><th>ЛР</th><th>Задание</th><th>Статус</th><th class="text-right">Действия</th></tr></thead>
|
||||
<table id="defense-table" class="tablekit">
|
||||
<thead><tr><th class="th-sortable is-asc" title="ФИО — по возрастанию">Студент</th><th>ЛР</th><th>Задание</th><th>Статус</th><th class="text-right" data-nosort>Действия</th></tr></thead>
|
||||
<tbody>
|
||||
<tr th:each="d : ${defenseRows}" th:attr="data-lab=${d.labId}">
|
||||
<td>
|
||||
@@ -162,10 +166,14 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">Студенты</h2>
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-2">
|
||||
<h2 class="section-title m-0">Студенты</h2>
|
||||
<input class="input input-sm table-search" data-target="students-table"
|
||||
placeholder="Поиск по студенту…" aria-label="Поиск по студентам">
|
||||
</div>
|
||||
<div class="card card-flush">
|
||||
<table>
|
||||
<thead><tr><th>№</th><th>ФИО</th><th>Логин</th><th>Основа</th><th>Варианты</th><th>Пароль</th><th class="text-right">Действия</th></tr></thead>
|
||||
<table id="students-table" class="tablekit">
|
||||
<thead><tr><th data-nosort>№</th><th class="th-sortable is-asc" title="ФИО — по возрастанию">ФИО</th><th>Логин</th><th>Основа</th><th>Варианты</th><th>Пароль</th><th class="text-right" data-nosort>Действия</th></tr></thead>
|
||||
<tbody>
|
||||
<tr th:each="row, iter : ${studentGrades}">
|
||||
<td class="text-muted" th:text="${iter.count}">1</td>
|
||||
|
||||
@@ -22,9 +22,14 @@
|
||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||
</form>
|
||||
</div>
|
||||
<div class="card card-flush mt-8">
|
||||
<table>
|
||||
<thead><tr><th>Название</th><th>Студентов</th><th>Выгрузка</th></tr></thead>
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-2 mt-8">
|
||||
<h2 class="section-title m-0">Список групп</h2>
|
||||
<input class="input input-sm table-search" data-target="groups-table"
|
||||
placeholder="Поиск по названию…" aria-label="Поиск по группам">
|
||||
</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>
|
||||
|
||||
@@ -71,13 +71,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div th:each="g : ${assignmentGroups}" class="card mb-4" th:if="${!#lists.isEmpty(g.students)}">
|
||||
<div th:each="g, gStat : ${assignmentGroups}" class="card mb-4" th:if="${!#lists.isEmpty(g.students)}">
|
||||
<div class="card-body">
|
||||
<h3 class="group-title" th:text="${g.groupName}">Группа</h3>
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-2">
|
||||
<h3 class="group-title m-0" th:text="${g.groupName}">Группа</h3>
|
||||
<input class="input input-sm table-search" th:attr="data-target='assign-table-' + ${gStat.index}"
|
||||
placeholder="Поиск по студенту…" aria-label="Поиск по студентам группы">
|
||||
</div>
|
||||
<div class="scroll-x">
|
||||
<table>
|
||||
<table class="tablekit" th:attr="id='assign-table-' + ${gStat.index}">
|
||||
<thead><tr>
|
||||
<th class="th-w-sm">Выбор</th><th>Студент</th><th class="th-w-md">Уровень</th><th class="th-w-md">Вариант</th>
|
||||
<th class="th-w-sm" data-nosort>Выбор</th><th class="th-sortable is-asc" title="ФИО — по возрастанию">Студент</th><th class="th-w-md">Уровень</th><th class="th-w-md">Вариант</th>
|
||||
<th class="th-w-sm">Источник</th><th>Сдача</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<div class="flex items-center justify-between gap-4 mb-6">
|
||||
<h1 class="page-title">Лабораторные</h1>
|
||||
<div class="flex gap-2">
|
||||
<input class="input input-sm table-search" data-target="labs-table"
|
||||
placeholder="Поиск по названию…" aria-label="Поиск по лабораторным">
|
||||
<button class="btn btn-secondary" type="button" onclick="openModal('modal-import-lab')">Импорт</button>
|
||||
<button class="btn btn-primary" type="button" onclick="openModal('modal-create-lab')">+ Создать</button>
|
||||
</div>
|
||||
@@ -16,8 +18,8 @@
|
||||
<div th:if="${error}" class="alert alert-error" th:text="${error}"></div>
|
||||
|
||||
<div class="card card-flush">
|
||||
<table>
|
||||
<thead><tr><th>№</th><th>Название</th><th>Вариантов</th><th>Статус</th><th></th></tr></thead>
|
||||
<table id="labs-table" class="tablekit">
|
||||
<thead><tr><th class="th-sortable is-asc" title="Номер — по возрастанию">№</th><th>Название</th><th>Вариантов</th><th>Статус</th><th data-nosort></th></tr></thead>
|
||||
<tbody>
|
||||
<tr th:each="lab : ${labs}">
|
||||
<td th:text="${lab.number}">1</td>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<link id="hljs-dark" rel="stylesheet" th:href="@{/css/hljs-github-dark.css}" disabled>
|
||||
<script th:src="@{/js/htmx.min.js}" defer></script>
|
||||
<script th:src="@{/js/highlight.min.js}" defer></script>
|
||||
<script th:src="@{/js/tablekit.js}" defer></script>
|
||||
<script>
|
||||
(function(){
|
||||
var t = localStorage.getItem('lms-theme') || 'light';
|
||||
|
||||
Reference in New Issue
Block a user