Rework on Bootstrap 5: standard navbar+offcanvas (fixed empty menu), Bootstrap Icons, complete B3 theme via BS vars, row/col grids
This commit is contained in:
@@ -5,18 +5,18 @@
|
||||
<div id="content">
|
||||
<h1 class="page-title">Панель преподавателя</h1>
|
||||
|
||||
<div class="grid grid-stats">
|
||||
<div class="card card-body"><p class="stat-title">Группы</p><p class="stat-value" th:text="${groupCount}">0</p></div>
|
||||
<div class="card card-body"><p class="stat-title">Студенты</p><p class="stat-value" th:text="${studentCount}">0</p></div>
|
||||
<div class="card card-body"><p class="stat-title">Лабораторные</p><p class="stat-value" th:text="${labCount}">0</p>
|
||||
<p class="hint" th:if="${labCount > 0}">опубликовано: <span th:text="${publishedLabs}">0</span></p></div>
|
||||
<div class="card card-body"><p class="stat-title">Средний балл</p>
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-xl-4 g-3">
|
||||
<div class="col"><div class="card card-body h-100"><p class="stat-title">Группы</p><p class="stat-value" th:text="${groupCount}">0</p></div></div>
|
||||
<div class="col"><div class="card card-body h-100"><p class="stat-title">Студенты</p><p class="stat-value" th:text="${studentCount}">0</p></div></div>
|
||||
<div class="col"><div class="card card-body h-100"><p class="stat-title">Лабораторные</p><p class="stat-value" th:text="${labCount}">0</p>
|
||||
<p class="hint" th:if="${labCount > 0}">опубликовано: <span th:text="${publishedLabs}">0</span></p></div></div>
|
||||
<div class="col"><div class="card card-body h-100"><p class="stat-title">Средний балл</p>
|
||||
<p class="stat-value" th:if="${avgGrade != null}" th:text="${#numbers.formatDecimal(avgGrade, 1, 2)}">—</p>
|
||||
<p class="stat-value text-muted" th:if="${avgGrade == null}">—</p></div>
|
||||
<p class="stat-value text-muted" th:if="${avgGrade == null}">—</p></div></div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-2 mt-8">
|
||||
<div>
|
||||
<div class="row g-4 mt-4">
|
||||
<div class="col-lg-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="section-title m-0">Лабораторные</h2>
|
||||
<a th:href="@{/admin/labs}" class="text-sm">Все лабораторные →</a>
|
||||
@@ -33,7 +33,7 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-lg-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="section-title m-0">Группы</h2>
|
||||
<a th:href="@{/admin/groups}" class="text-sm">Все группы →</a>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<button class="mini-btn" type="button"
|
||||
th:attr="data-url=@{/admin/groups/{id}/assign-modal(id=${group.id}, labId=${lab.id})},data-lab-name=|ЛР ${lab.number}|" data-action="assign"
|
||||
title="Выдача вариантов: уровни, варианты, автокраспределение по группе">
|
||||
<span class="cell-ico ico ico-menu" aria-hidden="true"></span>
|
||||
<i class="cell-ico ico bi bi-list" aria-hidden="true"></i>
|
||||
</button>
|
||||
<form class="inline-form" th:with="pub=${labPublication[lab.id]}, pc=${pub != null ? pub.publishedCount : 0}, all=${pub != null and pub.allPublished}"
|
||||
th:action="@{/admin/groups/{id}/publish(id=${group.id})}" method="post">
|
||||
@@ -61,8 +61,8 @@
|
||||
th:attr="data-lab=${lab.id},data-count=${pc},data-total=${pub != null ? pub.total : 0},data-all=${all}"
|
||||
th:classappend="${all} ? 'is-all' : (${pc > 0} ? 'is-partial' : 'is-empty')"
|
||||
th:title="${pub == null} ? '' : (${all} ? 'Оценки опубликованы всей группе — нажмите, чтобы скрыть у всех' : (${pc > 0} ? 'Опубликовано ' + ${pc} + ' из ' + ${pub.total} + ' — нажмите, чтобы опубликовать всем' : 'Показать оценки и комментарии всей группе'))">
|
||||
<span class="eye-open ico ico-eye-open" aria-hidden="true"></span>
|
||||
<span class="eye-closed ico ico-eye-closed" aria-hidden="true"></span>
|
||||
<i class="eye-open ico bi bi-eye" aria-hidden="true"></i>
|
||||
<i class="eye-closed ico bi bi-eye-slash" aria-hidden="true"></i>
|
||||
<span class="mini-count js-pub-count" th:classappend="(${all} or ${pc == 0}) ? 'is-hidden' : ''" th:text="${pc}"></span>
|
||||
</button>
|
||||
</form>
|
||||
@@ -278,20 +278,20 @@
|
||||
</form>
|
||||
<form class="form-stack mt-4" th:action="@{/admin/groups/{gid}/students/create(gid=${group.id})}" method="post">
|
||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="stNo">Студенческий номер (логин)</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="stNo">Студенческий номер (логин)</label>
|
||||
<input class="input" id="stNo" name="studentNo" required></div>
|
||||
<div><label class="label" for="stBasis">Основа обучения</label>
|
||||
<div class="col-md-6"><label class="label" for="stBasis">Основа обучения</label>
|
||||
<input class="input" id="stBasis" name="basis" placeholder="бюджет"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div><label class="label" for="stLast">Фамилия</label>
|
||||
<input class="input" id="stLast" name="lastName" required></div>
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="stFirst">Имя</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="stFirst">Имя</label>
|
||||
<input class="input" id="stFirst" name="firstName"></div>
|
||||
<div><label class="label" for="stMiddle">Отчество</label>
|
||||
<div class="col-md-6"><label class="label" for="stMiddle">Отчество</label>
|
||||
<input class="input" id="stMiddle" name="middleName"></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="hint">Новому студенту пароль будет сгенерирован автоматически.</p>
|
||||
<button class="btn btn-primary" type="submit">Создать нового</button>
|
||||
</form>
|
||||
|
||||
@@ -33,25 +33,25 @@
|
||||
<h2 class="section-title m-0">Условие лабораторной</h2>
|
||||
<button class="mini-btn" type="button" data-action="lab-edit"
|
||||
title="Редактировать параметры лабораторной" aria-label="Редактировать параметры лабораторной">
|
||||
<span class="cell-ico ico ico-pencil" aria-hidden="true"></span>
|
||||
<i class="cell-ico ico bi bi-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="card card-body md-body mb-6" id="lab-description-view" th:utext="${descriptionHtml}"></div>
|
||||
<form id="lab-edit-form" hidden class="card card-body form-stack mb-6" method="post"
|
||||
th:action="@{/admin/labs/{id}/edit(id=${lab.id})}">
|
||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="l-title">Название</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="l-title">Название</label>
|
||||
<input class="input" id="l-title" name="title" th:value="${lab.title}" required></div>
|
||||
<div><label class="label" for="l-points">Максимум баллов</label>
|
||||
<div class="col-md-6"><label class="label" for="l-points">Максимум баллов</label>
|
||||
<input class="input" id="l-points" name="pointsMax" type="number" step="0.1" min="0"
|
||||
th:value="${lab.pointsMax}" required></div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="l-deadline">Срок сдачи (время — МСК)</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="l-deadline">Срок сдачи (время — МСК)</label>
|
||||
<input class="input" id="l-deadline" name="deadlineAt" type="datetime-local"
|
||||
th:value="${deadlineLocal}"></div>
|
||||
<div><label class="label" for="l-defense">Дата защиты (время — МСК)</label>
|
||||
<div class="col-md-6"><label class="label" for="l-defense">Дата защиты (время — МСК)</label>
|
||||
<input class="input" id="l-defense" name="defenseAt" type="datetime-local" th:value="${defenseLocal}">
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,7 +82,7 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="mini-btn" type="button" th:attr="data-modal=|modal-level-rename-${level.id}|"
|
||||
title="Переименовать уровень" aria-label="Переименовать уровень">
|
||||
<span class="cell-ico ico ico-pencil" aria-hidden="true"></span>
|
||||
<i class="cell-ico ico bi bi-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
<form class="inline-form"
|
||||
th:action="@{/admin/labs/{labId}/levels/{levelId}/delete(labId=${lab.id}, levelId=${level.id})}"
|
||||
@@ -90,7 +90,7 @@
|
||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||
<button class="mini-btn danger" type="submit" title="Удалить уровень"
|
||||
aria-label="Удалить уровень">
|
||||
<span class="cell-ico ico ico-trash" aria-hidden="true"></span>
|
||||
<i class="cell-ico ico bi bi-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
<button class="btn btn-sm" type="button" th:attr="data-modal=|modal-variant-add-${level.id}|">+
|
||||
@@ -108,7 +108,7 @@
|
||||
<div class="flex gap-2">
|
||||
<button class="mini-btn" type="button" th:attr="data-modal=|modal-variant-edit-${v.id}|"
|
||||
title="Редактировать вариант" aria-label="Редактировать вариант">
|
||||
<span class="cell-ico ico ico-pencil" aria-hidden="true"></span>
|
||||
<i class="cell-ico ico bi bi-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
<form class="inline-form"
|
||||
th:action="@{/admin/labs/{labId}/variants/{variantId}/delete(labId=${lab.id}, variantId=${v.id})}"
|
||||
@@ -116,7 +116,7 @@
|
||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||
<button class="mini-btn danger" type="submit" title="Удалить вариант"
|
||||
aria-label="Удалить вариант">
|
||||
<span class="cell-ico ico ico-trash" aria-hidden="true"></span>
|
||||
<i class="cell-ico ico bi bi-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -154,12 +154,12 @@
|
||||
method="post">
|
||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||
<input type="hidden" name="labLevelId" th:value="${level.id}">
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="|va-number-${level.id}|">Номер</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="|va-number-${level.id}|">Номер</label>
|
||||
<input class="input" th:id="|va-number-${level.id}|" name="number" required></div>
|
||||
<div><label class="label" for="|va-title-${level.id}|">Название</label>
|
||||
<div class="col-md-6"><label class="label" for="|va-title-${level.id}|">Название</label>
|
||||
<input class="input" th:id="|va-title-${level.id}|" name="title"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div><label class="label" for="|va-statement-${level.id}|">Условие (markdown)</label>
|
||||
<textarea class="input" th:id="|va-statement-${level.id}|" name="statementMd"
|
||||
rows="8"></textarea></div>
|
||||
@@ -179,14 +179,14 @@
|
||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||
<input type="hidden" name="variantId" th:value="${v.id}">
|
||||
<input type="hidden" name="labLevelId" th:value="${level.id}">
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="|ve-number-${v.id}|">Номер</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="|ve-number-${v.id}|">Номер</label>
|
||||
<input class="input" th:id="|ve-number-${v.id}|" name="number" th:value="${v.number}"
|
||||
required></div>
|
||||
<div><label class="label" for="|ve-title-${v.id}|">Название</label>
|
||||
<div class="col-md-6"><label class="label" for="|ve-title-${v.id}|">Название</label>
|
||||
<input class="input" th:id="|ve-title-${v.id}|" name="title" th:value="${v.title}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div><label class="label" for="|ve-statement-${v.id}|">Условие (markdown)</label>
|
||||
<textarea class="input" th:id="|ve-statement-${v.id}|" name="statementMd" rows="10"
|
||||
th:text="${v.statementMd}"></textarea></div>
|
||||
|
||||
@@ -79,20 +79,20 @@
|
||||
</div>
|
||||
<div class="dlg-body">
|
||||
<form class="form-stack" th:action="@{/admin/labs/create}" method="post">
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="labNumber">Номер</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="labNumber">Номер</label>
|
||||
<input class="input" id="labNumber" name="number" type="number" min="1" required></div>
|
||||
<div><label class="label" for="labPoints">Максимум баллов</label>
|
||||
<div class="col-md-6"><label class="label" for="labPoints">Максимум баллов</label>
|
||||
<input class="input" id="labPoints" name="pointsMax" type="number" step="0.1" min="0" value="5" required></div>
|
||||
</div>
|
||||
</div>
|
||||
<div><label class="label" for="labTitle">Название</label>
|
||||
<input class="input" id="labTitle" name="title" required></div>
|
||||
<div class="grid grid-2">
|
||||
<div><label class="label" for="labDeadline">Срок сдачи</label>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="label" for="labDeadline">Срок сдачи</label>
|
||||
<input class="input" id="labDeadline" name="deadlineAt" type="datetime-local"></div>
|
||||
<div><label class="label" for="labDefense">Дата защиты</label>
|
||||
<div class="col-md-6"><label class="label" for="labDefense">Дата защиты</label>
|
||||
<input class="input" id="labDefense" name="defenseAt" type="datetime-local"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div><label class="label" for="labStatus">Статус</label>
|
||||
<select class="input" id="labStatus" name="status">
|
||||
<option value="draft">draft</option>
|
||||
|
||||
Reference in New Issue
Block a user