diff --git a/frontend/js/admin/sections/access.js b/frontend/js/admin/sections/access.js index aa26b92..2e1c955 100644 --- a/frontend/js/admin/sections/access.js +++ b/frontend/js/admin/sections/access.js @@ -396,7 +396,10 @@ /* ════════ режим «Матрица» (класс × контент одним экраном) ════════ */ function matrixHeadCells(classes) { return classes.map(c => - `${esc(c.name)}`).join(''); + ` + + `).join(''); } function matrixBody() { const classes = _matrix.classes || []; @@ -410,7 +413,10 @@ return ` `; }).join(''); - return `${esc(it.title)}${cells}`; + return ` + + ${cells}`; }).join(''); if (!rows) return ''; return `${TYPE_LABEL[type] || type}${rows}`; @@ -453,6 +459,40 @@ } function mxSearch(v) { _mSearch = v; const b = document.getElementById('acc-mx-body'); if (b) b.innerHTML = matrixBody(); } + function mxRepaint() { const b = document.getElementById('acc-mx-body'); if (b) b.innerHTML = matrixBody(); } + function mxApply(o, type, ref, open) { + const arr = o[type] || (o[type] = []); + const i = arr.indexOf(ref); + if (open && i < 0) arr.push(ref); + if (!open && i >= 0) arr.splice(i, 1); + } + /* строка матрицы: открыть/закрыть один контент всем классам */ + async function mxRowBulk(type, ref) { + const classes = _matrix.classes || []; + const allOpen = classes.length && classes.every(c => ((_matrix.open[c.id] || {})[type] || []).includes(ref)); + const open = !allOpen; + if (!open && !confirm(`Закрыть «${contentTitle(type, ref)}» у всех классов?`)) return; + try { + await Promise.all(classes.map(c => LS.accessSetRule(type, ref, 'class', c.id, open ? 1 : null))); + classes.forEach(c => mxApply(_matrix.open[c.id] || (_matrix.open[c.id] = {}), type, ref, open)); + mxRepaint(); + } catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); _matrix = null; renderMatrix(); } + } + /* столбец матрицы: открыть/закрыть весь контент одному классу */ + async function mxColBulk(classId) { + const items = CONTENT_TYPES.flatMap(t => itemsOf(t).map(it => [t, it[keyName(t)]])); + const o = _matrix.open[classId] || (_matrix.open[classId] = {}); + const allOpen = items.length && items.every(([t, ref]) => (o[t] || []).includes(ref)); + const open = !allOpen; + const cls = (_matrix.classes.find(c => c.id === classId) || {}).name || ('#' + classId); + if (!open && !confirm(`Закрыть весь контент у класса «${cls}»?`)) return; + try { + await Promise.all(items.map(([t, ref]) => LS.accessSetRule(t, ref, 'class', classId, open ? 1 : null))); + items.forEach(([t, ref]) => mxApply(o, t, ref, open)); + mxRepaint(); + } catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); _matrix = null; renderMatrix(); } + } + /* ── режим ── */ function setMode(m) { if (m === _mode) return; @@ -472,6 +512,8 @@ window.accClassBulk = classBulk; window.accMx = mxToggle; window.accMxSearch = mxSearch; + window.accMxRowBulk = mxRowBulk; + window.accMxColBulk = mxColBulk; window.accLeftSearch = leftSearch; window.AdminSections = window.AdminSections || {};