diff --git a/frontend/admin/css/components.css b/frontend/admin/css/components.css index 594da25..22d67bb 100755 --- a/frontend/admin/css/components.css +++ b/frontend/admin/css/components.css @@ -289,6 +289,25 @@ grid-template-columns: repeat(8, minmax(125px, 1fr)) auto; } +.subject-import-rows-list { + display: flex; + flex-direction: column; + gap: 0.75rem; + margin-top: 0.75rem; + overflow: visible; +} + +.subject-import-row { + display: grid; + grid-template-columns: minmax(120px, 1fr) minmax(200px, 3fr) auto; + gap: 0.75rem; + align-items: end; + padding: 0.75rem; + background: var(--bg-input); + border: 1px solid var(--bg-card-border); + border-radius: var(--radius-sm); +} + .schedule-rule-actions { margin-top: 0.25rem; clear: both; @@ -1259,6 +1278,10 @@ grid-template-columns: 1fr; } + .subject-import-row { + grid-template-columns: 1fr; + } + .calendar-fill-panel { grid-template-columns: 1fr; } diff --git a/frontend/admin/js/views/department-workspace.js b/frontend/admin/js/views/department-workspace.js index ab9208a..f2e55b8 100644 --- a/frontend/admin/js/views/department-workspace.js +++ b/frontend/admin/js/views/department-workspace.js @@ -12,6 +12,8 @@ export async function initDepartmentWorkspace() { const endInput = document.getElementById('department-workspace-end'); const refreshButton = document.getElementById('department-workspace-refresh'); const importForm = document.getElementById('department-subject-import-form'); + const importRowsContainer = document.getElementById('subject-import-rows'); + const importAddButton = document.getElementById('subject-import-add'); const subjectsTbody = document.getElementById('department-subjects-tbody'); const subjectCount = document.getElementById('department-subject-count'); const commentsCard = document.getElementById('department-comments-card'); @@ -32,6 +34,15 @@ export async function initDepartmentWorkspace() { startInput?.addEventListener('change', handleStartDateChange); endInput?.addEventListener('change', loadWorkload); importForm?.addEventListener('submit', importSubjects); + importAddButton?.addEventListener('click', () => renderImportRows([...readImportRows(), { code: '', name: '' }])); + importRowsContainer?.addEventListener('click', (event) => { + const removeBtn = event.target.closest('.subject-import-remove'); + if (removeBtn) { + const rows = readImportRows(); + rows.splice(Number(removeBtn.dataset.index), 1); + renderImportRows(rows.length ? rows : [{ code: '', name: '' }]); + } + }); commentsForm?.addEventListener('submit', saveComment); commentsCloseButton?.addEventListener('click', () => { commentsCard.hidden = true; @@ -50,6 +61,7 @@ export async function initDepartmentWorkspace() { departmentField.hidden = true; departmentSelect.value = userDepartmentId || ''; } + renderImportRows([{ code: '', name: '' }]); await loadWorkspace(); } catch (error) { showAlert('department-workspace-alert', error.message || 'Ошибка загрузки кабинета кафедры', 'error'); @@ -96,38 +108,57 @@ export async function initDepartmentWorkspace() { } } + function renderImportRows(rows) { + if (!importRowsContainer) return; + importRowsContainer.innerHTML = (rows || [{ code: '', name: '' }]).map((row, index) => ` +
+
+ + +
+
+ + +
+ +
+ `).join(''); + } + + function readImportRows() { + if (!importRowsContainer) return []; + return Array.from(importRowsContainer.querySelectorAll('.subject-import-row')).map(row => ({ + code: (row.querySelector('.subject-import-code')?.value || '').trim(), + name: (row.querySelector('.subject-import-name')?.value || '').trim() + })); + } + async function importSubjects(event) { event.preventDefault(); const alertId = 'department-subject-import-alert'; hideAlert(alertId); const departmentId = selectedDepartmentId(); - const rows = document.getElementById('department-subject-import-text').value - .split('\n') - .map(row => row.trim()) - .filter(Boolean) - .map(row => { - const [code, ...nameParts] = row.split(';'); - return { - code: (code || '').trim(), - name: nameParts.join(';').trim(), - departmentId: Number(departmentId) - }; - }) - .filter(item => item.name); + const rows = readImportRows() + .filter(item => item.name) + .map(item => ({ + code: item.code, + name: item.name, + departmentId: Number(departmentId) + })); if (!departmentId) { showAlert(alertId, 'Выберите кафедру', 'error'); return; } if (!rows.length) { - showAlert(alertId, 'Добавьте хотя бы одну строку в формате «код; название»', 'error'); + showAlert(alertId, 'Заполните название хотя бы одной дисциплины', 'error'); return; } try { const result = await api.post('/api/department/subjects/import', rows); showAlert(alertId, result.message || 'Дисциплины загружены', 'success'); - document.getElementById('department-subject-import-text').value = ''; + renderImportRows([{ code: '', name: '' }]); await loadSubjects(); } catch (error) { showAlert(alertId, error.message || 'Ошибка загрузки дисциплин', 'error'); diff --git a/frontend/admin/js/views/schedule.js b/frontend/admin/js/views/schedule.js index 02ecc74..7fc5a4b 100644 --- a/frontend/admin/js/views/schedule.js +++ b/frontend/admin/js/views/schedule.js @@ -416,9 +416,7 @@ export async function initSchedule() { if (!lessons.length) return ''; const oddLessons = lessons.filter(lesson => lesson.parity === 'BOTH' || lesson.parity === 'ODD'); const evenLessons = lessons.filter(lesson => lesson.parity === 'BOTH' || lesson.parity === 'EVEN'); - const shouldSplit = oddLessons.length > 0 - && evenLessons.length > 0 - && visualLessonSignature(oddLessons) !== visualLessonSignature(evenLessons); + const shouldSplit = lessons.some(l => l.parity !== 'BOTH'); if (!shouldSplit) { return `
${uniqueVisualLessons(lessons).map(renderVisualLesson).join('')}
`; @@ -1111,21 +1109,7 @@ export async function initSchedule() { function compactWeekRanges(weeks) { const uniqueWeeks = [...new Set((weeks || []).map(Number).filter(Boolean))].sort((a, b) => a - b); if (!uniqueWeeks.length) return ''; - const ranges = []; - let start = uniqueWeeks[0]; - let previous = uniqueWeeks[0]; - for (let index = 1; index < uniqueWeeks.length; index += 1) { - const week = uniqueWeeks[index]; - if (week === previous + 1) { - previous = week; - continue; - } - ranges.push(weekRangeText(start, previous)); - start = week; - previous = week; - } - ranges.push(weekRangeText(start, previous)); - return `(${ranges.join(', ')})`; + return `(${weekRangeText(uniqueWeeks[0], uniqueWeeks[uniqueWeeks.length - 1])})`; } function weekRangeText(start, end) { diff --git a/frontend/admin/views/department-workspace.html b/frontend/admin/views/department-workspace.html index 7539b7b..951fb12 100644 --- a/frontend/admin/views/department-workspace.html +++ b/frontend/admin/views/department-workspace.html @@ -30,9 +30,12 @@

Загрузка дисциплин

-
- - +
+
+ + +
+