fix: center attestation values and move password status

- widen attestation columns so full grade labels fit at the common font size
- center attestation values like the average score
- remove the password column and mark temporary/changed passwords with a square dot next to the student name
This commit is contained in:
2026-10-26 20:02:18 +03:00
parent 44edb5ebeb
commit d8e28e88fc
3 changed files with 15 additions and 15 deletions

View File

@@ -572,17 +572,16 @@ dialog.dlg.dlg-lg .dlg-body { max-height: 88vh; min-height: 62vh; }
.matrix tbody tr:last-child td { border-bottom: none; } .matrix tbody tr:last-child td { border-bottom: none; }
.matrix th.lab-col { min-width: 9.5rem; border-left: 1px solid var(--c-border); } .matrix th.lab-col { min-width: 9.5rem; border-left: 1px solid var(--c-border); }
.matrix td.cell-lab { min-width: 9.5rem; border-left: 1px solid var(--c-border); } .matrix td.cell-lab { min-width: 9.5rem; border-left: 1px solid var(--c-border); }
#group-table th.password-col,
#group-table th.average-col, #group-table th.average-col,
#group-table th.actions-head { color: var(--c-text); font-weight: 400; } #group-table th.actions-head { color: var(--c-text); font-weight: 400; }
#group-table th.actions-head, #group-table th.actions-head,
#group-table td.actions-cell { border-left: 1px solid var(--c-border); } #group-table td.actions-cell { border-left: 1px solid var(--c-border); }
.matrix th.attestation-col { .matrix th.attestation-col {
width: 11.5rem; min-width: 11rem; max-width: 11.5rem; width: 12rem; min-width: 11.5rem; max-width: 12rem;
border-left: 1px solid var(--c-border); border-left: 1px solid var(--c-border);
} }
.matrix td.attestation-cell { .matrix td.attestation-cell {
width: 11.5rem; min-width: 11rem; max-width: 11.5rem; width: 12rem; min-width: 11.5rem; max-width: 12rem;
padding-left: 0.35rem; padding-right: 0.35rem; padding-left: 0.35rem; padding-right: 0.35rem;
border-left: 1px solid var(--c-border); border-left: 1px solid var(--c-border);
} }
@@ -591,19 +590,17 @@ dialog.dlg.dlg-lg .dlg-body { max-height: 88vh; min-height: 62vh; }
min-width: 7rem; border-left: 1px solid var(--c-border); text-align: left; min-width: 7rem; border-left: 1px solid var(--c-border); text-align: left;
} }
.matrix td.average-cell { font-weight: 600; text-align: center; } .matrix td.average-cell { font-weight: 600; text-align: center; }
.matrix th.password-col,
.matrix td.password-cell { border-left: 1px solid var(--c-border); }
.attestation-title { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; width: 100%; max-width: 9rem; text-align: left; } .attestation-title { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; width: 100%; max-width: 9rem; text-align: left; }
.attestation-kind { font-weight: 400; color: var(--c-text); white-space: normal; text-align: left; } .attestation-kind { font-weight: 400; color: var(--c-text); white-space: normal; text-align: left; }
.attestation-col .lab-col-head, .attestation-col .lab-col-title { text-align: left; } .attestation-col .lab-col-head, .attestation-col .lab-col-title { text-align: left; }
.js-attestation-form { display: flex; justify-content: flex-start; width: 100%; } .js-attestation-form { display: flex; justify-content: center; width: 100%; }
.attestation-select { .attestation-select {
appearance: none; -webkit-appearance: none; appearance: none; -webkit-appearance: none;
width: 100%; max-width: 100%; min-width: 0; padding: 0.15rem 0.95rem 0.15rem 0.15rem; width: 100%; max-width: 100%; min-width: 0; padding: 0.15rem 0.95rem 0.15rem 0.15rem;
border: 1px solid transparent; border-radius: var(--radius-sm); border: 1px solid transparent; border-radius: var(--radius-sm);
background-color: transparent; color: var(--c-text); background-color: transparent; color: var(--c-text);
font-size: 0.84375rem; font-weight: 600; font-variant-numeric: tabular-nums; font-size: 0.84375rem; font-weight: 600; font-variant-numeric: tabular-nums;
text-align: left; text-align-last: left; cursor: pointer; text-align: center; text-align-last: center; cursor: pointer;
background-image: background-image:
linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(45deg, transparent 50%, currentColor 50%),
linear-gradient(135deg, currentColor 50%, transparent 50%); linear-gradient(135deg, currentColor 50%, transparent 50%);
@@ -617,6 +614,9 @@ dialog.dlg.dlg-lg .dlg-body { max-height: 88vh; min-height: 62vh; }
.attestation-select:disabled { opacity: 0.6; cursor: wait; } .attestation-select:disabled { opacity: 0.6; cursor: wait; }
.attestation-select option { text-align: left; text-align-last: left; background: var(--c-surface); color: var(--c-text); } .attestation-select option { text-align: left; text-align-last: left; background: var(--c-surface); color: var(--c-text); }
.matrix td.student-cell { min-width: 12rem; } .matrix td.student-cell { min-width: 12rem; }
.student-name-line { display: flex; align-items: center; gap: 0.35rem; }
.password-dot { width: 6px; height: 6px; flex: 0 0 auto; background: var(--c-tone-pos); }
.password-dot.warn { background: #b45309; }
.student-name { font-weight: 600; font-size: 0.84375rem; } .student-name { font-weight: 600; font-size: 0.84375rem; }
.student-cell .font-mono { margin-top: 0.125rem; } .student-cell .font-mono { margin-top: 0.125rem; }
.lab-col-head { display: flex; flex-direction: column; align-items: flex-start; gap: 0.375rem; } .lab-col-head { display: flex; flex-direction: column; align-items: flex-start; gap: 0.375rem; }

View File

@@ -105,14 +105,18 @@
</div> </div>
</div> </div>
</th> </th>
<th class="password-col" data-nosort>Пароль</th>
<th class="text-right actions-head" data-nosort>Действия</th> <th class="text-right actions-head" data-nosort>Действия</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr th:each="row : ${studentGrades}"> <tr th:each="row : ${studentGrades}">
<td class="student-cell matrix-sticky"> <td class="student-cell matrix-sticky">
<div class="student-name" th:text="${row.fullName}">—</div> <div class="student-name-line">
<span class="password-dot" th:classappend="${row.mustChangePassword} ? 'warn' : 'ok'"
th:title="${row.mustChangePassword} ? 'Системный пароль — требуется смена' : 'Пароль изменён'"
aria-label="Статус пароля"></span>
<div class="student-name" th:text="${row.fullName}">—</div>
</div>
<div class="text-sm text-muted font-mono" th:text="${row.studentNo}">—</div> <div class="text-sm text-muted font-mono" th:text="${row.studentNo}">—</div>
</td> </td>
<td th:each="cell, iterStat : ${row.cells}" class="text-center cell-lab" <td th:each="cell, iterStat : ${row.cells}" class="text-center cell-lab"
@@ -172,10 +176,6 @@
</select> </select>
</form> </form>
</td> </td>
<td class="password-cell">
<span th:if="${row.mustChangePassword}" class="badge badge-warn">временный</span>
<span th:unless="${row.mustChangePassword}" class="badge badge-ok">изменён</span>
</td>
<td class="text-right actions-cell"> <td class="text-right actions-cell">
<div class="actions-col"> <div class="actions-col">
<form th:action="@{/admin/groups/{gid}/students/{sid}/reset-password(gid=${group.id}, sid=${row.studentId})}" method="post" data-confirm="Сбросить пароль студенту? Текущий пароль перестанет работать, новый покажется один раз."> <form th:action="@{/admin/groups/{gid}/students/{sid}/reset-password(gid=${group.id}, sid=${row.studentId})}" method="post" data-confirm="Сбросить пароль студенту? Текущий пароль перестанет работать, новый покажется один раз.">
@@ -191,7 +191,7 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr th:if="${#lists.isEmpty(studentGrades)}"><td class="empty" th:attr="colspan=${#lists.size(labs) + #lists.size(attestations) + 4}">В группе нет студентов.</td></tr> <tr th:if="${#lists.isEmpty(studentGrades)}"><td class="empty" th:attr="colspan=${#lists.size(labs) + #lists.size(attestations) + 3}">В группе нет студентов.</td></tr>
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@@ -17,7 +17,7 @@
<!-- v=37: сброс кэша стилей после изменения геометрии; при изменении css поднимать версию --> <!-- v=37: сброс кэша стилей после изменения геометрии; при изменении css поднимать версию -->
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/css/bootstrap-icons.min.css}"> <link rel="stylesheet" th:href="@{/css/bootstrap-icons.min.css}">
<link rel="stylesheet" th:href="@{/css/app.css(v='50')}"> <link rel="stylesheet" th:href="@{/css/app.css(v='51')}">
<link id="hljs-light" rel="stylesheet" th:href="@{/css/hljs-github.css(v='36')}"> <link id="hljs-light" rel="stylesheet" th:href="@{/css/hljs-github.css(v='36')}">
<link id="hljs-dark" rel="stylesheet" th:href="@{/css/hljs-github-dark.css(v='36')}" disabled> <link id="hljs-dark" rel="stylesheet" th:href="@{/css/hljs-github-dark.css(v='36')}" disabled>
<script th:src="@{/js/highlight.min.js(v='36')}" defer></script> <script th:src="@{/js/highlight.min.js(v='36')}" defer></script>