92030b462c
Replace ~3500L admin.js monolith with thin orchestrator (~700L) + 14 IIFE-wrapped per-section modules under /js/admin/sections/. Section modules expose AdminSections.<name>.init/reload (lazy init via switchTab/router) and re-expose onclick handlers via window.X for backward compat. Shared helpers (MODES/DIFFS, fmtDate, pctClass, renderMath, qTypeBadge, pagination) live in /js/admin/_shared.js exposed on window.AdminCtx. switchTab now dispatches to AdminSections via ROUTE_TO_SECTION map; non-extracted system tabs (topics/audit/errors/health/classroom/avatars) remain inline in admin.js. user-panel overlay markup untouched — Phase 6 will remove it.
74 lines
2.7 KiB
JavaScript
74 lines
2.7 KiB
JavaScript
'use strict';
|
|
/* admin → tpl (templates: courses + lessons) section */
|
|
(function () {
|
|
'use strict';
|
|
let inited = false;
|
|
|
|
async function load() {
|
|
try {
|
|
const [courses, lessons] = await Promise.all([
|
|
LS.getCourseTemplates().catch(() => []),
|
|
LS.getLessonTemplates().catch(() => [])
|
|
]);
|
|
renderTplTable('tpl-course-body', courses, 'courses');
|
|
renderTplTable('tpl-lesson-body', lessons, 'lessons');
|
|
if (window.lucide) lucide.createIcons();
|
|
} catch(e) {
|
|
document.getElementById('tpl-course-body').innerHTML = `<tr><td colspan="7" class="error">Ошибка: ${esc(e.message)}</td></tr>`;
|
|
}
|
|
}
|
|
|
|
function renderTplTable(bodyId, items, type) {
|
|
const body = document.getElementById(bodyId);
|
|
if (!items || !items.length) {
|
|
body.innerHTML = '<tr><td colspan="7" class="empty">Нет шаблонов</td></tr>';
|
|
return;
|
|
}
|
|
body.innerHTML = items.map(t => `<tr>
|
|
<td>${t.id}</td>
|
|
<td><strong>${esc(t.name || t.title || '—')}</strong></td>
|
|
<td>${esc(t.subject || '—')}</td>
|
|
<td>${esc(t.category || '—')}</td>
|
|
<td>${esc(t.author_name || t.author || '—')}</td>
|
|
<td>
|
|
<label class="adm-toggle">
|
|
<input type="checkbox" ${t.is_public ? 'checked' : ''} onchange="tplTogglePublic('${type}', ${t.id}, this.checked)" />
|
|
<span class="track"></span><span class="thumb"></span>
|
|
</label>
|
|
</td>
|
|
<td>
|
|
<button class="btn-del-q" onclick="tplDelete('${type}', ${t.id})">Удалить</button>
|
|
</td>
|
|
</tr>`).join('');
|
|
}
|
|
|
|
async function tplTogglePublic(type, id, isPublic) {
|
|
try {
|
|
const endpoint = type === 'courses' ? '/api/templates/courses/' : '/api/templates/lessons/';
|
|
await LS.api(endpoint + id, { method: 'PUT', body: JSON.stringify({ is_public: isPublic ? 1 : 0 }) });
|
|
LS.toast(isPublic ? 'Шаблон опубликован' : 'Шаблон скрыт', 'success');
|
|
} catch(e) { LS.toast('Ошибка: ' + e.message, 'error'); }
|
|
}
|
|
|
|
async function tplDelete(type, id) {
|
|
if (!confirm('Удалить шаблон #' + id + '?')) return;
|
|
try {
|
|
if (type === 'courses') await LS.deleteCourseTemplate(id);
|
|
else await LS.deleteLessonTemplate(id);
|
|
LS.toast('Шаблон удалён', 'success');
|
|
inited = false;
|
|
await load();
|
|
inited = true;
|
|
} catch(e) { LS.toast('Ошибка: ' + e.message, 'error'); }
|
|
}
|
|
|
|
window.tplTogglePublic = tplTogglePublic;
|
|
window.tplDelete = tplDelete;
|
|
|
|
window.AdminSections = window.AdminSections || {};
|
|
window.AdminSections.tpl = {
|
|
init: async () => { if (inited) return; inited = true; await load(); },
|
|
reload: load,
|
|
};
|
|
})();
|