Исправил косяки в модалках решения конфликтов правил
This commit is contained in:
@@ -644,18 +644,26 @@
|
||||
|
||||
.schedule-conflict-modal {
|
||||
z-index: 1200;
|
||||
padding: 0.35rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.schedule-conflict-card {
|
||||
width: min(1440px, calc(100vw - 2rem));
|
||||
padding: 1.5rem;
|
||||
#schedule-conflict-modal .schedule-conflict-card {
|
||||
width: min(1760px, calc(100vw - 0.7rem));
|
||||
max-width: calc(100vw - 0.7rem);
|
||||
max-height: none;
|
||||
box-sizing: border-box;
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.schedule-conflict-head {
|
||||
display: grid;
|
||||
gap: 0.45rem;
|
||||
gap: 0.3rem;
|
||||
margin-right: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
margin-bottom: 0.65rem;
|
||||
}
|
||||
|
||||
.schedule-conflict-head h2 {
|
||||
@@ -669,7 +677,7 @@
|
||||
.schedule-conflict-head p {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.45;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.schedule-conflict-kicker {
|
||||
@@ -685,18 +693,46 @@
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.schedule-conflict-reasons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
|
||||
.schedule-conflict-reasons[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.schedule-conflict-reasons span {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.schedule-conflict-reasons strong {
|
||||
padding: 0.2rem 0.5rem;
|
||||
border: 1px solid rgba(245, 158, 11, 0.35);
|
||||
border-radius: 999px;
|
||||
background: rgba(245, 158, 11, 0.12);
|
||||
color: var(--warning);
|
||||
font-size: 0.76rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.schedule-conflict-rules {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.65rem;
|
||||
}
|
||||
|
||||
.schedule-conflict-rule-box {
|
||||
display: grid;
|
||||
gap: 0.35rem;
|
||||
gap: 0.25rem;
|
||||
min-width: 0;
|
||||
padding: 0.85rem;
|
||||
padding: 0.65rem;
|
||||
border: 1px solid var(--bg-card-border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-input);
|
||||
@@ -731,23 +767,25 @@
|
||||
|
||||
.schedule-conflict-form {
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.schedule-conflict-slots {
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
gap: 0.55rem;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
padding-right: 0.25rem;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.schedule-conflict-slot-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(210px, 1.15fr) minmax(130px, 0.7fr) minmax(140px, 0.75fr) minmax(170px, 0.85fr) minmax(240px, 1.15fr) minmax(190px, 1fr);
|
||||
gap: 0.65rem;
|
||||
grid-template-columns: minmax(160px, 1.05fr) minmax(104px, 0.72fr) minmax(112px, 0.72fr) minmax(132px, 0.85fr) minmax(190px, 1.2fr) minmax(160px, 0.95fr);
|
||||
gap: 0.5rem;
|
||||
align-items: end;
|
||||
padding: 0.75rem;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
padding: 0.6rem;
|
||||
border: 1px solid var(--bg-card-border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: color-mix(in srgb, var(--bg-input) 88%, transparent);
|
||||
@@ -761,11 +799,51 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.schedule-conflict-slot-fixed.schedule-conflict-field-hit {
|
||||
padding-left: 0.55rem;
|
||||
border-left: 3px solid rgba(245, 158, 11, 0.75);
|
||||
}
|
||||
|
||||
.schedule-conflict-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.schedule-conflict-card .form-group,
|
||||
.schedule-move-slot-card .form-group {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.schedule-conflict-card .form-group label,
|
||||
.schedule-move-slot-card .form-group label {
|
||||
margin-bottom: 0.28rem;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.schedule-conflict-card .form-group select,
|
||||
.schedule-move-slot-card .form-group select {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
padding: 0.55rem 0.65rem;
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
.schedule-conflict-card .form-alert,
|
||||
.schedule-move-slot-card .form-alert {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.schedule-conflict-field-hit label {
|
||||
color: var(--warning);
|
||||
}
|
||||
|
||||
.schedule-conflict-field-hit select {
|
||||
border-color: rgba(245, 158, 11, 0.65);
|
||||
background: color-mix(in srgb, rgba(245, 158, 11, 0.15) 35%, var(--bg-input));
|
||||
box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.12);
|
||||
}
|
||||
|
||||
.schedule-visual-context-menu {
|
||||
@@ -812,13 +890,24 @@
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
.schedule-move-slot-card {
|
||||
#schedule-move-slot-modal .schedule-move-slot-card {
|
||||
width: min(620px, calc(100vw - 2rem));
|
||||
box-sizing: border-box;
|
||||
margin: auto;
|
||||
max-height: none;
|
||||
padding: 1rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.schedule-move-slot-form {
|
||||
display: grid;
|
||||
gap: 0.9rem;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.schedule-conflict-slot-row {
|
||||
grid-template-columns: minmax(180px, 1.2fr) repeat(2, minmax(140px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
.subject-import-rows-list {
|
||||
@@ -1041,8 +1130,8 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.schedule-conflict-card {
|
||||
padding: 1.25rem;
|
||||
#schedule-conflict-modal .schedule-conflict-card {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.schedule-conflict-rules,
|
||||
@@ -1471,31 +1560,31 @@
|
||||
|
||||
.schedule-visual-edit-rule {
|
||||
position: absolute;
|
||||
top: 0.26rem;
|
||||
right: 0.26rem;
|
||||
top: 0.18rem;
|
||||
right: 0.2rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
width: 1rem;
|
||||
height: 1.25rem;
|
||||
padding: 0;
|
||||
border: 1px solid color-mix(in srgb, var(--accent) 36%, var(--bg-card-border));
|
||||
border-radius: 50%;
|
||||
background: color-mix(in srgb, var(--accent) 12%, var(--bg-card));
|
||||
color: var(--accent-hover);
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
color: var(--text-secondary);
|
||||
font: inherit;
|
||||
font-size: 0.82rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: background var(--transition), border-color var(--transition), color var(--transition), transform var(--transition);
|
||||
box-shadow: none;
|
||||
transition: color var(--transition), transform var(--transition);
|
||||
}
|
||||
|
||||
.schedule-visual-edit-rule:hover,
|
||||
.schedule-visual-edit-rule:focus-visible {
|
||||
border-color: var(--accent);
|
||||
background: color-mix(in srgb, var(--accent) 22%, var(--bg-card));
|
||||
color: var(--text-primary);
|
||||
background: transparent;
|
||||
color: var(--accent-hover);
|
||||
outline: none;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
@@ -73,3 +73,29 @@
|
||||
.modal-close:hover {
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
#schedule-conflict-modal {
|
||||
padding: 0.35rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#schedule-conflict-modal .modal-content {
|
||||
width: min(1760px, calc(100vw - 0.7rem));
|
||||
max-width: calc(100vw - 0.7rem);
|
||||
max-height: none;
|
||||
box-sizing: border-box;
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#schedule-move-slot-modal .modal-content {
|
||||
width: min(620px, calc(100vw - 2rem));
|
||||
max-width: calc(100vw - 2rem);
|
||||
max-height: none;
|
||||
box-sizing: border-box;
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ export async function initSchedule() {
|
||||
const conflictSubmitButton = document.getElementById('schedule-conflict-submit');
|
||||
const conflictSlotsContainer = document.getElementById('schedule-conflict-slots');
|
||||
const conflictSummary = document.getElementById('schedule-conflict-summary');
|
||||
const conflictReasons = document.getElementById('schedule-conflict-reasons');
|
||||
const conflictNewRuleTitle = document.getElementById('schedule-conflict-new-rule');
|
||||
const conflictNewRuleMeta = document.getElementById('schedule-conflict-new-rule-meta');
|
||||
const conflictExistingRuleTitle = document.getElementById('schedule-conflict-existing-rule');
|
||||
@@ -1046,6 +1047,7 @@ export async function initSchedule() {
|
||||
const conflictRule = error.data.conflictRule;
|
||||
pendingConflictResolution = {
|
||||
conflictRule: clonePlain(conflictRule),
|
||||
conflictFields: Array.isArray(error.data.conflictFields) ? [...error.data.conflictFields] : [],
|
||||
pendingPayload: clonePlain(pendingPayload),
|
||||
pendingRuleId: pendingRuleId || ''
|
||||
};
|
||||
@@ -1064,7 +1066,8 @@ export async function initSchedule() {
|
||||
if (conflictExistingRuleMeta) {
|
||||
conflictExistingRuleMeta.textContent = ruleMeta(conflictRule);
|
||||
}
|
||||
renderConflictSlots(conflictRule);
|
||||
renderConflictReasons(pendingConflictResolution.conflictFields, error.data.conflictReasons);
|
||||
renderConflictSlots(conflictRule, pendingConflictResolution.conflictFields);
|
||||
hideAlert('schedule-conflict-alert');
|
||||
conflictModal?.classList.add('open');
|
||||
conflictModal?.setAttribute('aria-hidden', 'false');
|
||||
@@ -1075,6 +1078,10 @@ export async function initSchedule() {
|
||||
conflictModal?.classList.remove('open');
|
||||
conflictModal?.setAttribute('aria-hidden', 'true');
|
||||
if (conflictSlotsContainer) conflictSlotsContainer.innerHTML = '';
|
||||
if (conflictReasons) {
|
||||
conflictReasons.hidden = true;
|
||||
conflictReasons.innerHTML = '';
|
||||
}
|
||||
hideAlert('schedule-conflict-alert');
|
||||
}
|
||||
|
||||
@@ -1138,7 +1145,24 @@ export async function initSchedule() {
|
||||
}
|
||||
}
|
||||
|
||||
function renderConflictSlots(rule) {
|
||||
function renderConflictReasons(fields, reasons) {
|
||||
if (!conflictReasons) return;
|
||||
const labels = Array.isArray(reasons) && reasons.length
|
||||
? reasons
|
||||
: (fields || []).map(conflictFieldLabel).filter(Boolean);
|
||||
if (!labels.length) {
|
||||
conflictReasons.hidden = true;
|
||||
conflictReasons.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
conflictReasons.hidden = false;
|
||||
conflictReasons.innerHTML = `
|
||||
<span>Причина:</span>
|
||||
${labels.map(label => `<strong>${escapeHtml(label)}</strong>`).join('')}
|
||||
`;
|
||||
}
|
||||
|
||||
function renderConflictSlots(rule, conflictFields = []) {
|
||||
const slots = rule.slots || [];
|
||||
if (!conflictSlotsContainer) return;
|
||||
if (!slots.length) {
|
||||
@@ -1151,9 +1175,10 @@ export async function initSchedule() {
|
||||
slot.lessonFormat,
|
||||
slotSubgroupNames(slot).join(', ')
|
||||
].filter(Boolean);
|
||||
const groupHitClass = conflictFieldClass('group', conflictFields);
|
||||
return `
|
||||
<section class="schedule-conflict-slot-row" data-index="${index}">
|
||||
<div class="schedule-conflict-slot-fixed">
|
||||
<div class="schedule-conflict-slot-fixed ${groupHitClass}">
|
||||
<span>Слот ${index + 1}</span>
|
||||
<strong>${escapeHtml(fixedParts.join(' · ') || 'Занятие')}</strong>
|
||||
<small>${escapeHtml(conflictSlotCurrentText(slot))}</small>
|
||||
@@ -1161,13 +1186,24 @@ export async function initSchedule() {
|
||||
<div class="form-group"><label>День</label><select class="conflict-slot-day" required>${options(DAY_OPTIONS, slot.dayOfWeek)}</select></div>
|
||||
<div class="form-group"><label>Чётность</label><select class="conflict-slot-parity" required>${options(Object.entries(PARITY_LABELS).map(([value, label]) => ({ value, label })), slot.parity || 'BOTH')}</select></div>
|
||||
<div class="form-group"><label>Пара</label><select class="conflict-slot-time" required>${options(timeSlots.map(toTimeSlotOption), slot.timeSlotId)}</select></div>
|
||||
<div class="form-group"><label>Преподаватель</label><select class="conflict-slot-teacher" required>${options(teachers.map(toTeacherOption), slot.teacherId)}</select></div>
|
||||
<div class="form-group"><label>Аудитория</label><select class="conflict-slot-classroom" required>${options(classrooms.map(toClassroomOption), slot.classroomId)}</select></div>
|
||||
<div class="form-group ${conflictFieldClass('teacher', conflictFields)}"><label>Преподаватель</label><select class="conflict-slot-teacher" required>${options(teachers.map(toTeacherOption), slot.teacherId)}</select></div>
|
||||
<div class="form-group ${conflictFieldClass('classroom', conflictFields)}"><label>Аудитория</label><select class="conflict-slot-classroom" required>${options(classrooms.map(toClassroomOption), slot.classroomId)}</select></div>
|
||||
</section>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function conflictFieldClass(field, fields) {
|
||||
return (fields || []).includes(field) ? 'schedule-conflict-field-hit' : '';
|
||||
}
|
||||
|
||||
function conflictFieldLabel(field) {
|
||||
if (field === 'teacher') return 'Преподаватель';
|
||||
if (field === 'classroom') return 'Аудитория';
|
||||
if (field === 'group') return 'Группа';
|
||||
return field;
|
||||
}
|
||||
|
||||
function readConflictSlots(validate) {
|
||||
const conflictRule = pendingConflictResolution?.conflictRule;
|
||||
const rows = Array.from(conflictSlotsContainer?.querySelectorAll('.schedule-conflict-slot-row') || []);
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
<span class="schedule-conflict-kicker">Конфликт слота</span>
|
||||
<h2>Освободите место для нового правила</h2>
|
||||
<p id="schedule-conflict-summary">Ранее созданное правило занимает выбранное время, преподавателя или аудиторию.</p>
|
||||
<div class="schedule-conflict-reasons" id="schedule-conflict-reasons" hidden></div>
|
||||
</div>
|
||||
<div class="schedule-conflict-rules">
|
||||
<section class="schedule-conflict-rule-box">
|
||||
|
||||
Reference in New Issue
Block a user