Changeset 0.16.0 (#74)
This commit is contained in:
@@ -400,6 +400,42 @@ async function settingsDeleteTeamPreset(teamId, presetId, name) {
|
||||
|
||||
// ── Team Provider handlers — now managed by UI primitives in ui-settings.js ──
|
||||
|
||||
// ── Group Actions ───────────────────────────
|
||||
|
||||
async function deleteGroup(id, name) {
|
||||
if (!await showConfirm(`Delete group "${name}"? Members will lose access to any resources granted via this group.`)) return;
|
||||
try { await API.adminDeleteGroup(id); UI.toast('Group deleted'); await UI.loadAdminGroups(); }
|
||||
catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function removeGroupMember(groupId, userId, label) {
|
||||
if (!await showConfirm(`Remove ${label} from group?`)) return;
|
||||
try {
|
||||
await API.adminRemoveGroupMember(groupId, userId);
|
||||
UI.toast('Member removed');
|
||||
await UI.loadGroupMembers(groupId);
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function saveGrant(resourceType, resourceId) {
|
||||
const scopeSel = document.getElementById(`grantScope_${resourceId}`);
|
||||
if (!scopeSel) return;
|
||||
const scope = scopeSel.value;
|
||||
const groupsDiv = document.getElementById(`grantGroups_${resourceId}`);
|
||||
const selectedGroups = [...(groupsDiv?.querySelectorAll('.grant-group-cb:checked') || [])].map(cb => cb.value);
|
||||
|
||||
if (scope === 'groups' && selectedGroups.length === 0) {
|
||||
return UI.toast('Select at least one group', 'error');
|
||||
}
|
||||
|
||||
try {
|
||||
await API.adminSetGrant(resourceType, resourceId, scope, selectedGroups);
|
||||
// Remove the picker
|
||||
document.querySelectorAll('.grant-picker-active').forEach(el => el.remove());
|
||||
UI.toast(scope === 'team_only' ? 'Access reverted to team only' : `Access set to ${scope}`);
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
// ── Admin Listeners (extracted from initListeners) ──
|
||||
|
||||
function _initAdminListeners() {
|
||||
@@ -509,6 +545,66 @@ function _initAdminListeners() {
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
});
|
||||
|
||||
// ── Group management ────────────────────────
|
||||
document.getElementById('adminAddGroupBtn')?.addEventListener('click', async () => {
|
||||
document.getElementById('adminAddGroupForm').style.display = '';
|
||||
document.getElementById('adminGroupName').focus();
|
||||
// Populate team dropdown
|
||||
try {
|
||||
const resp = await API.adminListTeams();
|
||||
const teams = (resp.data || []).filter(t => t.is_active);
|
||||
const sel = document.getElementById('adminGroupTeam');
|
||||
sel.innerHTML = '<option value="">Select team...</option>' +
|
||||
teams.map(t => `<option value="${t.id}">${esc(t.name)}</option>`).join('');
|
||||
} catch (e) { /* proceed without teams */ }
|
||||
});
|
||||
document.getElementById('adminGroupScope')?.addEventListener('change', function() {
|
||||
document.getElementById('adminGroupTeamRow').style.display = this.value === 'team' ? '' : 'none';
|
||||
});
|
||||
document.getElementById('adminCancelGroupBtn')?.addEventListener('click', () => {
|
||||
document.getElementById('adminAddGroupForm').style.display = 'none';
|
||||
document.getElementById('adminGroupName').value = '';
|
||||
document.getElementById('adminGroupDesc').value = '';
|
||||
});
|
||||
document.getElementById('adminCreateGroupBtn')?.addEventListener('click', async () => {
|
||||
const name = document.getElementById('adminGroupName').value.trim();
|
||||
const desc = document.getElementById('adminGroupDesc').value.trim();
|
||||
const scope = document.getElementById('adminGroupScope').value;
|
||||
const teamId = scope === 'team' ? document.getElementById('adminGroupTeam').value : null;
|
||||
if (!name) return UI.toast('Group name required', 'error');
|
||||
if (scope === 'team' && !teamId) return UI.toast('Select a team for team-scoped groups', 'error');
|
||||
try {
|
||||
await API.adminCreateGroup(name, desc, scope, teamId);
|
||||
document.getElementById('adminAddGroupForm').style.display = 'none';
|
||||
document.getElementById('adminGroupName').value = '';
|
||||
document.getElementById('adminGroupDesc').value = '';
|
||||
UI.toast('Group created');
|
||||
await UI.loadAdminGroups(true);
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
});
|
||||
document.getElementById('adminGroupBackBtn')?.addEventListener('click', () => {
|
||||
document.getElementById('adminGroupDetail').style.display = 'none';
|
||||
document.getElementById('adminGroupList').style.display = '';
|
||||
UI.loadAdminGroups(true);
|
||||
});
|
||||
document.getElementById('adminAddGroupMemberBtn')?.addEventListener('click', async () => {
|
||||
document.getElementById('adminAddGroupMemberForm').style.display = '';
|
||||
await UI.loadGroupMemberDropdown(UI._groupEditId);
|
||||
});
|
||||
document.getElementById('adminCancelGroupMemberBtn')?.addEventListener('click', () => {
|
||||
document.getElementById('adminAddGroupMemberForm').style.display = 'none';
|
||||
});
|
||||
document.getElementById('adminAddGroupMemberSubmit')?.addEventListener('click', async () => {
|
||||
const userId = document.getElementById('adminGroupMemberUser').value;
|
||||
if (!userId) return UI.toast('Select a user', 'error');
|
||||
try {
|
||||
await API.adminAddGroupMember(UI._groupEditId, userId);
|
||||
document.getElementById('adminAddGroupMemberForm').style.display = 'none';
|
||||
UI.toast('Member added');
|
||||
await UI.loadGroupMembers(UI._groupEditId);
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
});
|
||||
|
||||
// ── Extension management ────────────────────
|
||||
document.getElementById('adminInstallExtBtn')?.addEventListener('click', () => {
|
||||
document.getElementById('adminInstallExtForm').style.display = '';
|
||||
|
||||
Reference in New Issue
Block a user