Files
Learn_System/frontend/js/admin/sections/tpl.js
T
Maxim Dolgolyov 92030b462c feat(admin): phase 2 — split admin.js into 13 section modules
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.
2026-05-16 22:50:14 +03:00

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,
};
})();