V0.1
This commit is contained in:
137
public/js/pages/options.js
Normal file
137
public/js/pages/options.js
Normal file
@@ -0,0 +1,137 @@
|
||||
import { apiGet, apiPost, apiPut, isAuthRedirectError } from '../api.js';
|
||||
import { guard } from '../core/auth-guard.js';
|
||||
import { esc, formatDeSyncDateTime } 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 renderSyncLog(entries) {
|
||||
const tbody = document.getElementById('sync-log-body');
|
||||
if (!entries.length) {
|
||||
tbody.innerHTML =
|
||||
'<tr><td colspan="5" class="muted">Noch keine Einträge.</td></tr>';
|
||||
return;
|
||||
}
|
||||
tbody.innerHTML = entries
|
||||
.map(
|
||||
(e) => `
|
||||
<tr>
|
||||
<td>${esc(formatDeSyncDateTime(e.finishedAt))}</td>
|
||||
<td>${e.triggerType === 'automatic' ? 'Automatisch' : 'Manuell'}</td>
|
||||
<td><span class="sync-status-badge ${e.status === 'success' ? 'sync-status-ok' : 'sync-status-err'}">${e.status === 'success' ? 'Erfolg' : 'Fehler'}</span></td>
|
||||
<td class="num">${esc(String(e.usersSynced ?? 0))}</td>
|
||||
<td>${e.errorMessage ? esc(e.errorMessage) : '—'}</td>
|
||||
</tr>`,
|
||||
)
|
||||
.join('');
|
||||
}
|
||||
|
||||
function applyIntegrationForm(data) {
|
||||
const ldap = data.ldap || {};
|
||||
document.getElementById('ldap_syncEnabled').checked = Boolean(ldap.syncEnabled);
|
||||
document.getElementById('ldap_serverUrl').value = ldap.serverUrl ?? '';
|
||||
document.getElementById('ldap_searchBase').value = ldap.searchBase ?? '';
|
||||
document.getElementById('ldap_bindDn').value = ldap.bindDn ?? '';
|
||||
document.getElementById('ldap_bindPassword').value = '';
|
||||
document.getElementById('ldap_userSearchFilter').value =
|
||||
ldap.userSearchFilter || ldap.userFilter || '';
|
||||
document.getElementById('ldap_usernameAttribute').value =
|
||||
ldap.usernameAttribute ?? '';
|
||||
document.getElementById('ldap_firstNameAttribute').value =
|
||||
ldap.firstNameAttribute ?? '';
|
||||
document.getElementById('ldap_lastNameAttribute').value =
|
||||
ldap.lastNameAttribute ?? '';
|
||||
document.getElementById('ldap_syncIntervalMinutes').value = String(
|
||||
ldap.syncIntervalMinutes ?? 1440,
|
||||
);
|
||||
|
||||
const tv = data.teamviewer || {};
|
||||
document.getElementById('tv_bearerToken').value =
|
||||
tv.bearerToken || tv.apiToken || '';
|
||||
document.getElementById('tv_notes').value = tv.notes ?? tv.apiNotes ?? '';
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const data = await apiGet('/settings/integrations');
|
||||
let syncStatus = { lastSyncAt: null, entries: [] };
|
||||
try {
|
||||
syncStatus = await apiGet('/ldap/sync-status');
|
||||
} catch {
|
||||
/* ältere Server */
|
||||
}
|
||||
|
||||
applyIntegrationForm(data);
|
||||
document.getElementById('ldap-last-sync').textContent =
|
||||
`Letzte Synchronisation: ${formatDeSyncDateTime(syncStatus.lastSyncAt)}`;
|
||||
renderSyncLog(Array.isArray(syncStatus.entries) ? syncStatus.entries : []);
|
||||
|
||||
const ldapBody = document.getElementById('ldap-section-body');
|
||||
const ldapToggle = document.getElementById('ldap-toggle');
|
||||
const chev = ldapToggle.querySelector('.ldap-chevron');
|
||||
function setLdapOpen(open) {
|
||||
ldapBody.hidden = !open;
|
||||
ldapToggle.setAttribute('aria-expanded', String(open));
|
||||
chev.textContent = open ? '▲' : '▼';
|
||||
}
|
||||
ldapToggle.onclick = () => setLdapOpen(ldapBody.hidden);
|
||||
|
||||
document.getElementById('btn-ldap-sync-now').onclick = async () => {
|
||||
const btn = document.getElementById('btn-ldap-sync-now');
|
||||
btn.disabled = true;
|
||||
try {
|
||||
await apiPost('/ldap/sync', {});
|
||||
location.reload();
|
||||
} catch (err) {
|
||||
alert(err.message || String(err));
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById('form-opt').onsubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const fd = new FormData(e.target);
|
||||
await apiPut('/settings/integrations', {
|
||||
ldap: {
|
||||
serverUrl: fd.get('ldap_serverUrl'),
|
||||
bindDn: fd.get('ldap_bindDn'),
|
||||
bindPassword: fd.get('ldap_bindPassword'),
|
||||
searchBase: fd.get('ldap_searchBase'),
|
||||
userSearchFilter: fd.get('ldap_userSearchFilter'),
|
||||
usernameAttribute: fd.get('ldap_usernameAttribute'),
|
||||
firstNameAttribute: fd.get('ldap_firstNameAttribute'),
|
||||
lastNameAttribute: fd.get('ldap_lastNameAttribute'),
|
||||
syncIntervalMinutes: fd.get('ldap_syncIntervalMinutes'),
|
||||
syncEnabled: fd.get('ldap_syncEnabled') === 'on',
|
||||
},
|
||||
teamviewer: {
|
||||
bearerToken: fd.get('tv_bearerToken'),
|
||||
notes: fd.get('tv_notes'),
|
||||
},
|
||||
});
|
||||
location.reload();
|
||||
};
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const st = await guard({ needsAdmin: true, activeNav: 'options' });
|
||||
if (!st) return;
|
||||
loadingEl.hidden = true;
|
||||
mainEl.hidden = false;
|
||||
try {
|
||||
await run();
|
||||
} catch (e) {
|
||||
if (isAuthRedirectError(e)) return;
|
||||
showError(e.message || 'Fehler');
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
Reference in New Issue
Block a user