Group users by company + allow admins to set user/admin role
- Superadmin sees users grouped by company with header rows - Admins can now set user or admin role when creating/editing users - Admin role change restricted to own company only - Prevents admin from modifying superadmin roles Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
107
script.js
107
script.js
@@ -1160,23 +1160,64 @@ async function loadUsers() {
|
||||
try {
|
||||
const users = await apiCall('users');
|
||||
const utbody = document.getElementById('users-tbody');
|
||||
utbody.innerHTML = users.map(u => `<tr>
|
||||
<td><strong>${esc(u.username)}</strong></td>
|
||||
<td>${esc(u.nimi)}</td>
|
||||
<td>${esc(u.email || '')}</td>
|
||||
<td>${u.role === 'superadmin' ? '<span class="role-badge role-superadmin">Pääkäyttäjä</span>' :
|
||||
(u.company_roles || {})[currentCompany?.id] === 'admin'
|
||||
? '<span class="role-badge role-admin">Admin</span>'
|
||||
: '<span class="role-badge role-user">Käyttäjä</span>'}</td>
|
||||
<td>${esc(u.luotu)}</td>
|
||||
<td class="actions-cell">
|
||||
<button onclick="editUser('${u.id}')" title="Muokkaa">✎</button>
|
||||
${u.id !== '${currentUser.id}' ? `<button onclick="deleteUser('${u.id}','${esc(u.username)}')" title="Poista">🗑</button>` : ''}
|
||||
</td>
|
||||
</tr>`).join('');
|
||||
const isSA = currentUser?.role === 'superadmin';
|
||||
|
||||
if (isSA) {
|
||||
// Superadmin: ryhmittele yrityskohtaisesti
|
||||
const companyMap = {}; // companyId => { name, users }
|
||||
const noCompany = [];
|
||||
users.forEach(u => {
|
||||
const comps = u.companies || [];
|
||||
if (comps.length === 0) {
|
||||
noCompany.push(u);
|
||||
} else {
|
||||
comps.forEach(cid => {
|
||||
if (!companyMap[cid]) {
|
||||
const comp = availableCompanies.find(c => c.id === cid);
|
||||
companyMap[cid] = { name: comp?.nimi || cid, users: [] };
|
||||
}
|
||||
companyMap[cid].users.push(u);
|
||||
});
|
||||
}
|
||||
});
|
||||
// Järjestä yritykset nimen mukaan
|
||||
const sortedCompanies = Object.entries(companyMap).sort((a, b) => a[1].name.localeCompare(b[1].name));
|
||||
let html = '';
|
||||
for (const [cid, group] of sortedCompanies) {
|
||||
html += `<tr><td colspan="6" style="background:#e8ecf1;font-weight:700;color:#0f3460;padding:10px 12px;font-size:0.95rem;border-top:2px solid #c8d0da;">${esc(group.name)}</td></tr>`;
|
||||
html += group.users.map(u => renderUserRow(u, cid)).join('');
|
||||
}
|
||||
if (noCompany.length) {
|
||||
html += `<tr><td colspan="6" style="background:#f5f0e8;font-weight:700;color:#888;padding:10px 12px;font-size:0.95rem;border-top:2px solid #e0d8c8;">Ei yritystä</td></tr>`;
|
||||
html += noCompany.map(u => renderUserRow(u, null)).join('');
|
||||
}
|
||||
utbody.innerHTML = html;
|
||||
} else {
|
||||
// Admin: flat-lista omasta yrityksestä
|
||||
utbody.innerHTML = users.map(u => renderUserRow(u, currentCompany?.id)).join('');
|
||||
}
|
||||
} catch (e) { console.error(e); }
|
||||
}
|
||||
|
||||
function renderUserRow(u, companyId) {
|
||||
const role = u.role === 'superadmin'
|
||||
? '<span class="role-badge role-superadmin">Pääkäyttäjä</span>'
|
||||
: (u.company_roles || {})[companyId] === 'admin'
|
||||
? '<span class="role-badge role-admin">Admin</span>'
|
||||
: '<span class="role-badge role-user">Käyttäjä</span>';
|
||||
return `<tr>
|
||||
<td><strong>${esc(u.username)}</strong></td>
|
||||
<td>${esc(u.nimi)}</td>
|
||||
<td>${esc(u.email || '')}</td>
|
||||
<td>${role}</td>
|
||||
<td>${esc(u.luotu)}</td>
|
||||
<td class="actions-cell">
|
||||
<button onclick="editUser('${u.id}')" title="Muokkaa">✎</button>
|
||||
${u.id !== currentUser?.id ? `<button onclick="deleteUser('${u.id}','${esc(u.username)}')" title="Poista">🗑</button>` : ''}
|
||||
</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
let usersCache = [];
|
||||
document.getElementById('btn-add-user').addEventListener('click', () => openUserForm());
|
||||
document.getElementById('user-modal-close').addEventListener('click', () => userModal.style.display = 'none');
|
||||
@@ -1196,9 +1237,24 @@ function openUserForm(user = null) {
|
||||
// Piilota superadmin-kenttä ellei ole superadmin
|
||||
const roleGroup = document.getElementById('user-role-group');
|
||||
if (roleGroup) roleGroup.style.display = currentUser?.role === 'superadmin' ? '' : 'none';
|
||||
// Piilota yrityscheckboxit adminilta (näkee vain oman yrityksen)
|
||||
// Piilota yrityscheckboxit adminilta (näkee vain oman yrityksen), mutta näytä yrityskohtainen rooli
|
||||
const isSuperAdmin = currentUser?.role === 'superadmin';
|
||||
const compSection = document.getElementById('user-company-checkboxes')?.closest('.form-group');
|
||||
if (compSection) compSection.style.display = currentUser?.role === 'superadmin' ? '' : 'none';
|
||||
if (compSection) compSection.style.display = isSuperAdmin ? '' : 'none';
|
||||
// Admin-näkymä: yrityskohtainen rooli omalle yritykselle
|
||||
const adminRoleSection = document.getElementById('admin-company-role-section');
|
||||
if (adminRoleSection) {
|
||||
if (!isSuperAdmin && currentUser?.company_role === 'admin') {
|
||||
adminRoleSection.style.display = '';
|
||||
const adminRoleSelect = document.getElementById('admin-company-role-select');
|
||||
if (adminRoleSelect) {
|
||||
const currentRole = (user?.company_roles || {})[currentCompany?.id] || 'user';
|
||||
adminRoleSelect.value = currentRole;
|
||||
}
|
||||
} else {
|
||||
adminRoleSection.style.display = 'none';
|
||||
}
|
||||
}
|
||||
// Yrityscheckboxit + yrityskohtaiset roolit
|
||||
const allComps = availableCompanies.length > 0 ? availableCompanies : [];
|
||||
const userComps = user ? (user.companies || []) : [];
|
||||
@@ -1282,12 +1338,21 @@ document.getElementById('user-form').addEventListener('submit', async (e) => {
|
||||
const companies = [...document.querySelectorAll('.user-company-cb:checked')].map(cb => cb.value);
|
||||
// Kerää yrityskohtaiset roolit
|
||||
const company_roles = {};
|
||||
document.querySelectorAll('.user-company-role').forEach(sel => {
|
||||
const cid = sel.dataset.companyId;
|
||||
if (companies.includes(cid)) {
|
||||
company_roles[cid] = sel.value;
|
||||
if (currentUser?.role === 'superadmin') {
|
||||
// Superadmin: kerää kaikista yritys-dropdowneista
|
||||
document.querySelectorAll('.user-company-role').forEach(sel => {
|
||||
const cid = sel.dataset.companyId;
|
||||
if (companies.includes(cid)) {
|
||||
company_roles[cid] = sel.value;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Admin: käytä admin-company-role-select omalle yritykselle
|
||||
const adminRoleSelect = document.getElementById('admin-company-role-select');
|
||||
if (adminRoleSelect && currentCompany?.id) {
|
||||
company_roles[currentCompany.id] = adminRoleSelect.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Kerää allekirjoitukset
|
||||
const signatures = {};
|
||||
document.querySelectorAll('.sig-textarea').forEach(ta => {
|
||||
|
||||
Reference in New Issue
Block a user