'use strict'; /* admin → access section — открыть/закрыть доступ к учебникам и экзаменам * для классов и отдельных учеников. Модель allowlist: по умолчанию закрыто, * правило ученика важнее правила класса. */ (function () { 'use strict'; let inited = false; let _catalog = null; // { textbooks:[], exams:[] } let _targets = null; // { classes:[{id,name,students:[]}], looseStudents:[] } let _sel = null; // { type:'textbook'|'exam', ref, title } let _rules = { classRules: {}, studentRules: {} }; const _open = new Set(); // class ids развёрнутых строк const esc = (s) => (window.LS && LS.esc ? LS.esc(s) : String(s == null ? '' : s)); async function load() { try { [_catalog, _targets] = await Promise.all([LS.accessCatalog(), LS.accessTargets()]); renderList(); } catch (e) { document.getElementById('acc-textbooks').innerHTML = `
Ошибка загрузки: ${esc(e.message)}
`; } } function itemBtn(type, ref, title, sub) { const active = _sel && _sel.type === type && _sel.ref === ref; return ``; } function renderList() { const tb = document.getElementById('acc-textbooks'); const ex = document.getElementById('acc-exams'); tb.innerHTML = (_catalog.textbooks || []) .map(t => itemBtn('textbook', t.slug, t.title, t.grade ? t.grade + ' кл.' : '')).join('') || 'Нет учебников
'; ex.innerHTML = (_catalog.exams || []) .map(e => itemBtn('exam', e.exam_key, e.title, e.grade ? e.grade + ' кл.' : '')).join('') || 'Нет экзаменов
'; } async function select(type, ref) { const src = type === 'textbook' ? _catalog.textbooks : _catalog.exams; const keyName = type === 'textbook' ? 'slug' : 'exam_key'; const item = (src || []).find(x => x[keyName] === ref); _sel = { type, ref, title: item ? item.title : ref }; renderList(); document.getElementById('acc-detail-empty').style.display = 'none'; const det = document.getElementById('acc-detail'); det.style.display = ''; det.innerHTML = 'Загрузка…
'; try { _rules = await LS.accessRules(type, ref); renderDetail(); } catch (e) { det.innerHTML = `Ошибка: ${esc(e.message)}
`; } } /* tri-state кнопки для ученика внутри класса */ function studentTri(uid) { const v = _rules.studentRules[uid]; // 1 | 0 | undefined const state = v === 1 ? 'open' : v === 0 ? 'closed' : 'inherit'; const btn = (val, label, on) => ``; return ` ${btn('null', 'Наследовать', state === 'inherit')} ${btn(1, 'Открыт', state === 'open')} ${btn(0, 'Закрыт', state === 'closed')} `; } function classRow(c) { const openToClass = _rules.classRules[c.id] === 1; const expanded = _open.has(c.id); const students = c.students || []; const studentsHtml = expanded ? `В классе нет учеников
'}Нет классов.
'}