Admin group: single table, defense actions in cells; flash messages as toasts
This commit is contained in:
@@ -200,6 +200,33 @@ tr:last-child td { border-bottom: none; }
|
||||
/* Toast-уведомление */
|
||||
.toast { position: fixed; top: 1rem; right: 1rem; z-index: 50; width: 20rem; }
|
||||
|
||||
/* Всплывающие уведомления (flash notice/error) вместо статичных алертов */
|
||||
.toast-host {
|
||||
position: fixed; top: 1rem; right: 1rem; z-index: 100;
|
||||
display: flex; flex-direction: column; gap: 0.5rem;
|
||||
width: min(24rem, calc(100vw - 2rem)); pointer-events: none;
|
||||
}
|
||||
.toast-item {
|
||||
pointer-events: auto; display: flex; align-items: flex-start; gap: 0.5rem;
|
||||
padding: 0.7rem 0.85rem; border-radius: 0.5rem; border: 1px solid var(--c-border);
|
||||
border-left-width: 4px; background: var(--c-surface); color: var(--c-text);
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
animation: toast-in 0.18s ease-out;
|
||||
}
|
||||
.toast-item .toast-text { flex: 1 1 auto; min-width: 0; white-space: pre-line; overflow-wrap: anywhere; }
|
||||
.toast-item.toast-success { border-left-color: #16a34a; }
|
||||
.toast-item.toast-error { border-left-color: #dc2626; }
|
||||
.toast-item.toast-warning { border-left-color: #d97706; }
|
||||
.toast-close {
|
||||
flex: 0 0 auto; border: none; background: none; cursor: pointer;
|
||||
color: var(--c-text-muted); font-size: 1.05rem; line-height: 1; padding: 0 0.1rem;
|
||||
}
|
||||
.toast-close:hover { color: var(--c-text); }
|
||||
@keyframes toast-in {
|
||||
from { opacity: 0; transform: translateY(-6px); }
|
||||
to { opacity: 1; transform: none; }
|
||||
}
|
||||
|
||||
/* Modals */
|
||||
dialog.modal {
|
||||
border: none; border-radius: 0.75rem; padding: 0;
|
||||
|
||||
@@ -65,9 +65,10 @@ function csSerialize() {
|
||||
$id('grade-comments').value = JSON.stringify(out);
|
||||
}
|
||||
|
||||
/* ---------- Индивидуальные задания (защита) ---------- */
|
||||
/* ---------- Индивидуальное задание (защита) ---------- */
|
||||
|
||||
function openDefenseForm(btn) {
|
||||
/** Открывает диалог задания; кнопка может не нести data-* (тогда это «назначить новое»). */
|
||||
function openDefense(btn) {
|
||||
var form = $id('defense-form');
|
||||
if (!form) return;
|
||||
form.reset();
|
||||
@@ -76,29 +77,41 @@ function openDefenseForm(btn) {
|
||||
if (student) $id('defense-student-select').value = student;
|
||||
if (lab) $id('defense-lab-select').value = lab;
|
||||
$id('defense-md').value = btn.getAttribute('data-md') || '';
|
||||
|
||||
var session = btn.getAttribute('data-session') || '';
|
||||
var status = btn.getAttribute('data-status') || '';
|
||||
var actions = $id('defense-actions');
|
||||
if (session) {
|
||||
$id('defense-issue-form').action = '/admin/defenses/' + session + '/issue-code';
|
||||
$id('defense-reset-form').action = '/admin/defenses/' + session + '/reset';
|
||||
if ($id('defense-action-lab')) $id('defense-action-lab').value = lab;
|
||||
if ($id('defense-reset-lab')) $id('defense-reset-lab').value = lab;
|
||||
$id('defense-reset-form').hidden = status !== 'ready';
|
||||
if (actions) actions.hidden = false;
|
||||
} else if (actions) {
|
||||
actions.hidden = true;
|
||||
}
|
||||
|
||||
var d = $id('modal-defense');
|
||||
if (d && d.showModal) d.showModal();
|
||||
}
|
||||
|
||||
function showDefenseText(btn) {
|
||||
function showDefenseFromModal() {
|
||||
var el = $id('defense-text-body');
|
||||
if (el) el.textContent = btn.getAttribute('data-md') || '(пусто)';
|
||||
if (el) el.textContent = $id('defense-md').value || '(пусто)';
|
||||
var title = $id('defense-text-title');
|
||||
if (title) title.textContent = (btn.getAttribute('data-student-name') || '') + ' — ' + (btn.getAttribute('data-lab-name') || '');
|
||||
if (title) {
|
||||
var s = $id('defense-student-select');
|
||||
var l = $id('defense-lab-select');
|
||||
var who = s && s.selectedOptions[0] ? s.selectedOptions[0].textContent : '';
|
||||
var lab = l && l.selectedOptions[0] ? l.selectedOptions[0].textContent : '';
|
||||
title.textContent = who + ' — ' + lab;
|
||||
}
|
||||
var d = $id('modal-defense-text');
|
||||
if (d && d.showModal) d.showModal();
|
||||
}
|
||||
|
||||
function filterDefense() {
|
||||
var s = $id('defense-lab-filter');
|
||||
if (!s) return;
|
||||
var labId = s.value;
|
||||
document.querySelectorAll('#defense-table tr[data-lab]').forEach(function (tr) {
|
||||
tr.style.display = (!labId || tr.getAttribute('data-lab') === labId) ? '' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------- Матрица: фокус на лабораторной и закрепление варианта ---------- */
|
||||
/* ---------- Матрица: фокус на лабораторной ---------- */
|
||||
|
||||
function focusLab() {
|
||||
var s = $id('lab-focus');
|
||||
@@ -113,4 +126,4 @@ document.addEventListener('submit', function (ev) {
|
||||
if (ev.target && ev.target.id === 'grade-form') csSerialize();
|
||||
}, true);
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function () { filterDefense(); focusLab(); });
|
||||
window.addEventListener('DOMContentLoaded', function () { focusLab(); });
|
||||
|
||||
Reference in New Issue
Block a user