// Page script for admin.html. Bootstrapping (auth cookie check, /info fetch,
// header rendering, active-nav highlight) lives in js/app.js; this file wires
// the "add user" form and the removable user list, and swaps between the
// unauthorized / not-admin / admin panels depending on the /info payload.
CollabCentral.init(function (ctx) {
if (!ctx.info.isAdmin) {
document.getElementById('notAdminPanel').classList.remove('hidden');
return;
}
document.getElementById('adminPanel').classList.remove('hidden');
var labelEl = document.getElementById('botLabelInline');
if (labelEl && ctx.info.label) labelEl.textContent = ctx.info.label;
loadUsers();
});
function loadUsers() {
fetch('/CollabCentral/' + CollabCentral.appName + '/admin/users')
.then(function (res) {
if (!res.ok) throw new Error('HTTP ' + res.status);
return res.json();
})
.then(renderUsers)
.catch(function (err) {
console.error('Failed to load users:', err);
flashAddStatus('Could not load the user list.', true);
});
}
function renderUsers(users) {
var listEl = document.getElementById('userList');
var emptyEl = document.getElementById('userListEmpty');
if (!listEl) return;
listEl.innerHTML = '';
if (!users || !users.length) {
emptyEl.classList.remove('hidden');
return;
}
emptyEl.classList.add('hidden');
users
.slice()
.sort(function (a, b) {
return String(a.displayName || '').localeCompare(String(b.displayName || ''));
})
.forEach(function (u) { listEl.appendChild(userRow(u)); });
}
function userRow(user) {
var li = document.createElement('li');
li.className = 'userRow';
var avatar = document.createElement('div');
avatar.className = 'userRow__avatar';
if (user.avatar) {
avatar.style.backgroundImage = 'url(' + JSON.stringify(user.avatar) + ')';
} else {
avatar.textContent = (user.displayName || '?').slice(0, 1).toUpperCase();
avatar.classList.add('userRow__avatar--initials');
}
li.appendChild(avatar);
var meta = document.createElement('div');
meta.className = 'userRow__meta';
var name = document.createElement('div');
name.className = 'userRow__name';
name.textContent = user.displayName || '(no display name)';
var email = document.createElement('div');
email.className = 'userRow__email';
email.textContent = user.email || '';
var stats = document.createElement('div');
stats.className = 'userRow__stats';
stats.textContent = (user.groupCount === 1)
? '1 favorite group'
: (user.groupCount || 0) + ' favorite groups';
meta.appendChild(name);
meta.appendChild(email);
meta.appendChild(stats);
li.appendChild(meta);
var actions = document.createElement('div');
actions.className = 'userRow__actions';
var removeBtn = document.createElement('button');
removeBtn.type = 'button';
removeBtn.className = 'btn btn-danger';
removeBtn.textContent = 'Remove';
removeBtn.dataset.userId = user.id;
removeBtn.dataset.userName = user.displayName || '';
removeBtn.addEventListener('click', onRemoveUser);
actions.appendChild(removeBtn);
li.appendChild(actions);
return li;
}
function onRemoveUser(event) {
var btn = event.currentTarget;
var userId = btn.dataset.userId;
var userName = btn.dataset.userName || 'this user';
if (!userId) return;
if (!window.confirm('Remove ' + userName + ' from this bot?')) return;
btn.disabled = true;
fetch('/CollabCentral/' + CollabCentral.appName + '/admin/users/' + encodeURIComponent(userId), {
method: 'DELETE'
})
.then(function (res) {
if (!res.ok) throw new Error('HTTP ' + res.status);
return res.json();
})
.then(function (body) {
renderUsers(body.users || []);
flashAddStatus('Removed ' + userName + '.');
})
.catch(function (err) {
console.error('Failed to remove user:', err);
btn.disabled = false;
flashAddStatus('Could not remove ' + userName + '.', true);
});
}
document.getElementById('addUserForm').addEventListener('submit', function (event) {
event.preventDefault();
var input = document.getElementById('newUserEmail');
var email = (input.value || '').trim();
if (!email) return;
var submitBtn = event.target.querySelector('button[type="submit"]');
submitBtn.disabled = true;
fetch('/CollabCentral/' + CollabCentral.appName + '/admin/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email })
})
.then(function (res) {
return res.json().then(function (body) { return { ok: res.ok, status: res.status, body: body }; })
.catch(function () { return { ok: res.ok, status: res.status, body: null }; });
})
.then(function (result) {
if (result.ok) {
renderUsers((result.body && result.body.users) || []);
var added = result.body && result.body.user;
flashAddStatus(added
? 'Added ' + (added.displayName || added.email) + '.'
: 'User added.');
input.value = '';
} else if (result.status === 404) {
flashAddStatus('No Webex user found for that email.', true);
} else if (result.status === 403) {
flashAddStatus('You are not an administrator.', true);
} else if (result.status === 502) {
flashAddStatus('Could not reach the Webex directory. Try again.', true);
} else {
flashAddStatus('Something went wrong. Please try again.', true);
}
})
.catch(function (err) {
console.error('Failed to add user:', err);
flashAddStatus('Network error while adding user.', true);
})
.finally(function () {
submitBtn.disabled = false;
});
});
function flashAddStatus(text, isError) {
var el = document.getElementById('addUserStatus');
if (!el) return;
el.textContent = text;
el.classList.toggle('fieldStatus--error', !!isError);
clearTimeout(flashAddStatus._t);
flashAddStatus._t = setTimeout(function () {
el.textContent = '';
el.classList.remove('fieldStatus--error');
}, 5000);
}