feat(permissions): C-4b — админ-UI конструктора ролей + назначение пользователю
Клиент: listRoles/createRole/updateRoleDef/deleteRole/rolePermissions. Во вкладке «Доступ · роли» — блок «Конструктор ролей»: создать роль (имя-идентификатор + название + базовые роли чекбоксами), список кастомных ролей, «Настроить права» (тогглы по группам через getRolePermissions + setPermission под именем роли), «Удалить» (возврат пользователей на базу). В списке пользователей выпадающий список ролей теперь включает optgroup «Кастомные роли» (выбор по custom_role); listUsers отдаёт custom_role. Phase C (произвольные роли) завершена на ветке. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
let _usersPage = 1;
|
||||
const _USERS_PER_PAGE = 50;
|
||||
let _customRoles = []; // кастомные роли для выпадающего списка назначения
|
||||
|
||||
/* ── one-time CSS injection for hover row-actions (shared with sessions) ── */
|
||||
function ensureRowActionsStyles() {
|
||||
@@ -65,6 +66,7 @@
|
||||
try {
|
||||
const r = await LS.adminGetUsers({ page: _usersPage, limit: _USERS_PER_PAGE });
|
||||
const users = r.users || [];
|
||||
try { _customRoles = (await LS.listRoles()).filter(x => !x.isBuiltin); } catch { _customRoles = []; }
|
||||
const tbody = document.getElementById('users-body');
|
||||
if (!users.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="7"><div class="empty">Пользователей нет</div></td></tr>';
|
||||
@@ -77,10 +79,11 @@
|
||||
const avatarBg = u.role==='admin' ? 'linear-gradient(135deg,#9B5DE5,#c084fc)' : u.role==='teacher' ? 'linear-gradient(135deg,#06D6E0,#9B5DE5)' : u.role==='free_student' ? 'linear-gradient(135deg,#10B981,#059669)' : 'linear-gradient(135deg,#8898AA,#3D4F6B)';
|
||||
const roleCell = isAdmin && u.id !== user.id
|
||||
? `<select class="role-select" data-uid="${u.id}" onchange="changeRole(this)">
|
||||
<option value="student" ${u.role==='student' ?'selected':''}>Ученик</option>
|
||||
<option value="free_student" ${u.role==='free_student' ?'selected':''}>Своб. ученик</option>
|
||||
<option value="teacher" ${u.role==='teacher' ?'selected':''}>Учитель</option>
|
||||
<option value="admin" ${u.role==='admin' ?'selected':''}>Админ</option>
|
||||
<option value="student" ${(!u.custom_role && u.role==='student') ?'selected':''}>Ученик</option>
|
||||
<option value="free_student" ${(!u.custom_role && u.role==='free_student') ?'selected':''}>Своб. ученик</option>
|
||||
<option value="teacher" ${(!u.custom_role && u.role==='teacher') ?'selected':''}>Учитель</option>
|
||||
<option value="admin" ${(!u.custom_role && u.role==='admin') ?'selected':''}>Админ</option>
|
||||
${_customRoles.length ? '<optgroup label="Кастомные роли">' + _customRoles.map(cr => `<option value="${esc(cr.name)}" ${u.custom_role===cr.name?'selected':''}>${esc(cr.label)}</option>`).join('') + '</optgroup>' : ''}
|
||||
</select>`
|
||||
: `<span class="role-badge ${u.role}">${{student:'Ученик',free_student:'Своб. ученик',teacher:'Учитель',admin:'Админ'}[u.role]||u.role}</span>`;
|
||||
return `<tr class="clickable${u.is_banned ? ' banned-row' : ''}" onclick="AdminRouter.navigate('#users/${u.id}')">
|
||||
|
||||
Reference in New Issue
Block a user