Files
SDS-CRM/public/js/pages/users.js

136 lines
4.4 KiB
JavaScript

import { apiDelete, apiGet, apiPost, apiPut, isAuthRedirectError } from '../api.js';
import { guard } from '../core/auth-guard.js';
import { esc } from '../core/utils.js';
const loadingEl = document.getElementById('page-loading');
const mainEl = document.getElementById('page-main');
const errEl = document.getElementById('page-error');
function showError(msg) {
loadingEl.hidden = true;
mainEl.hidden = true;
errEl.hidden = false;
errEl.textContent = msg;
}
function formatName(u) {
const a = [u.firstName, u.lastName].filter(Boolean);
return a.length ? a.map((x) => esc(String(x))).join(' ') : '—';
}
function roleOptionsHtml(current) {
const opts = [
['viewer', 'Viewer'],
['after_sales', 'After-Sales'],
['admin', 'Administrator'],
];
return opts
.map(
([val, label]) =>
`<option value="${esc(val)}"${current === val ? ' selected' : ''}>${esc(label)}</option>`,
)
.join('');
}
function renderRows(users) {
const tbody = document.getElementById('users-table-body');
tbody.innerHTML = users
.map(
(u) => `
<tr data-id="${esc(u.id)}">
<td>${esc(u.username)}</td>
<td class="muted">${formatName(u)}</td>
<td>
<select id="role-${esc(u.id)}" class="user-role-select" data-user-id="${esc(u.id)}" data-role-prev="${esc(u.role)}" aria-label="Rolle">
${roleOptionsHtml(u.role)}
</select>
</td>
<td class="muted">${u.source === 'ldap' ? 'LDAP' : 'Lokal'}</td>
<td>${u.active ? 'Ja' : 'Nein'}</td>
<td class="users-actions">
${u.source === 'local' ? `<button type="button" class="secondary btn-pw" data-id="${esc(u.id)}">Passwort</button>` : ''}
<button type="button" class="secondary btn-toggle" data-id="${esc(u.id)}" data-active="${u.active ? '1' : '0'}">${u.active ? 'Deaktivieren' : 'Aktivieren'}</button>
<button type="button" class="danger btn-del-user" data-id="${esc(u.id)}">Löschen</button>
</td>
</tr>`,
)
.join('');
}
async function run() {
const users = await apiGet('/users');
renderRows(users);
document.getElementById('form-new-user').onsubmit = async (e) => {
e.preventDefault();
const fd = new FormData(e.target);
await apiPost('/users', {
username: fd.get('username'),
password: fd.get('password'),
role: fd.get('role'),
});
e.target.reset();
location.reload();
};
const root = document.getElementById('page-main');
root.querySelectorAll('.user-role-select').forEach((sel) => {
sel.addEventListener('change', async () => {
const id = sel.getAttribute('data-user-id');
const prev = sel.getAttribute('data-role-prev');
const role = sel.value;
sel.disabled = true;
try {
await apiPut(`/users/${id}`, { role });
sel.setAttribute('data-role-prev', role);
} catch (e) {
window.alert(e.message || 'Rolle konnte nicht gespeichert werden.');
sel.value = prev;
} finally {
sel.disabled = false;
}
});
});
root.querySelectorAll('.btn-pw').forEach((btn) => {
btn.onclick = async () => {
const uid = btn.getAttribute('data-id');
const pw = window.prompt('Neues Passwort (min. 8 Zeichen):');
if (!pw || pw.length < 8) return;
await apiPut(`/users/${uid}`, { password: pw });
location.reload();
};
});
root.querySelectorAll('.btn-toggle').forEach((btn) => {
btn.onclick = async () => {
const uid = btn.getAttribute('data-id');
const active = btn.getAttribute('data-active') === '1';
await apiPut(`/users/${uid}`, { active: !active });
location.reload();
};
});
root.querySelectorAll('.btn-del-user').forEach((btn) => {
btn.onclick = async () => {
if (!window.confirm('Benutzer wirklich löschen?')) return;
const uid = btn.getAttribute('data-id');
await apiDelete(`/users/${uid}`);
location.reload();
};
});
}
async function init() {
const st = await guard({ needsAdmin: true, activeNav: 'users' });
if (!st) return;
loadingEl.hidden = true;
mainEl.hidden = false;
try {
await run();
} catch (e) {
if (isAuthRedirectError(e)) return;
showError(e.message || 'Fehler');
}
}
init();