This commit is contained in:
2026-01-13 00:05:49 +01:00
parent 47327a12e0
commit 4f271a8560
7 changed files with 94 additions and 51 deletions

View File

@@ -4,6 +4,7 @@ $appBaseUrl = $GLOBALS['app_base_url'] ?? '';
$defaultNavLinks = [
['id' => 'dashboard', 'label' => 'Dashboard', 'href' => $appBaseUrl . '/admin/dashboard.php'],
['id' => 'settings', 'label' => 'API & Tabellen', 'href' => $appBaseUrl . '/admin/settings.php'],
['id' => 'users', 'label' => 'Userverwaltung', 'href' => $appBaseUrl . '/admin/users.php'],
['id' => 'profile', 'label' => 'Mein Konto', 'href' => $appBaseUrl . '/admin/profile.php'],
];

View File

@@ -6,48 +6,6 @@ require __DIR__ . '/accountsetup_config.php';
require dirname(__DIR__) . '/../structure/layout_start.php';
?>
<main class="max-w-5xl mx-auto p-4 md:p-6 flex-1 w-full space-y-6">
<section class="section-card" data-role="owner">
<div class="flex items-center justify-between mb-3">
<h4>Team</h4>
<button type="button" id="btn-user-add" class="btn">+ Nutzer</button>
</div>
<div class="overflow-auto">
<table class="team-table" id="teamTable">
<thead>
<tr><th>Name</th><th>E-Mail</th><th>Rolle</th><th>Status</th><th class="text-right">Aktionen</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
<form id="userForm" class="space-y-3 mt-4 hidden">
<input type="hidden" name="user_id">
<label class="block text-sm text-slate-600">Name
<input type="text" name="name" class="input mt-1" required>
</label>
<label class="block text-sm text-slate-600">E-Mail
<input type="email" name="email" class="input mt-1" required>
</label>
<label class="block text-sm text-slate-600">Rolle
<select name="role" class="input mt-1">
<option value="owner">Owner</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="viewer">Viewer</option>
</select>
</label>
<label class="inline-flex items-center gap-2 text-sm text-slate-600">
<input type="checkbox" name="is_active" checked> Aktiv
</label>
<label class="inline-flex items-center gap-2 text-sm text-slate-600 reset-only hidden">
<input type="checkbox" name="reset_password"> Passwort zurücksetzen
</label>
<div class="flex justify-end gap-2">
<button type="button" id="userFormCancel" class="btn">Abbrechen</button>
<button type="submit" class="btn">Speichern</button>
</div>
</form>
</section>
<section class="section-card" data-role="admin">
<div class="flex items-center justify-between mb-3">
<h4>Absender für Testmails</h4>
@@ -152,7 +110,7 @@ require dirname(__DIR__) . '/../structure/layout_start.php';
<div id="toast-root"></div>
<dialog id="bridgeSetupDialog" class="rounded-xl max-w-4xl w-[92vw]">
<dialog id="bridgeSetupDialog" class="rounded-xl max-w-4xl w-[92vw] p-5">
<div class="flex items-center justify-between gap-3 border-b border-slate-200 pb-3 mb-4">
<h3 class="text-lg font-semibold">Bridge-Setup</h3>
<button type="button" id="btn-close-bridge-setup" class="btn">Schliessen</button>

View File

@@ -0,0 +1,56 @@
<?php
$pageTitle = 'Email Template System Userverwaltung';
$pageId = 'admin';
$navActive = 'users';
require __DIR__ . '/accountsetup_config.php';
require dirname(__DIR__) . '/../structure/layout_start.php';
?>
<main class="max-w-5xl mx-auto p-4 md:p-6 flex-1 w-full space-y-6">
<section class="section-card" data-role="owner">
<div class="flex items-center justify-between mb-3">
<h4>Team</h4>
<button type="button" id="btn-user-add" class="btn">+ Nutzer</button>
</div>
<div class="overflow-auto">
<table class="team-table" id="teamTable">
<thead>
<tr><th>Name</th><th>E-Mail</th><th>Rolle</th><th>Status</th><th class="text-right">Aktionen</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
<form id="userForm" class="space-y-3 mt-4 hidden">
<input type="hidden" name="user_id">
<label class="block text-sm text-slate-600">Name
<input type="text" name="name" class="input mt-1" required>
</label>
<label class="block text-sm text-slate-600">E-Mail
<input type="email" name="email" class="input mt-1" required>
</label>
<label class="block text-sm text-slate-600">Rolle
<select name="role" class="input mt-1">
<option value="owner">Owner</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="viewer">Viewer</option>
</select>
</label>
<label class="inline-flex items-center gap-2 text-sm text-slate-600">
<input type="checkbox" name="is_active" checked> Aktiv
</label>
<label class="inline-flex items-center gap-2 text-sm text-slate-600 reset-only hidden">
<input type="checkbox" name="reset_password"> Passwort zurücksetzen
</label>
<div class="flex justify-end gap-2">
<button type="button" id="userFormCancel" class="btn">Abbrechen</button>
<button type="submit" class="btn">Speichern</button>
</div>
</form>
</section>
</main>
<div id="toast-root"></div>
<?php
tpl_add_script(app_asset_url('/assets/js/toast.js'));
tpl_add_script(app_asset_url('/assets/js/account.js'), 'footer', false, false, '', null, true);
require dirname(__DIR__) . '/../structure/layout_end.php';

View File

@@ -5,6 +5,7 @@ $appBaseUrl = $layoutContext['app_base_url'] ?? '';
$navLinks = $navLinks ?? [
['id' => 'dashboard', 'label' => 'Dashboard', 'href' => $appBaseUrl . '/admin/dashboard.php'],
['id' => 'settings', 'label' => 'API & Tabellen', 'href' => $appBaseUrl . '/admin/settings.php'],
['id' => 'users', 'label' => 'Userverwaltung', 'href' => $appBaseUrl . '/admin/users.php'],
['id' => 'profile', 'label' => 'Mein Konto', 'href' => $appBaseUrl . '/admin/profile.php'],
];
@@ -48,6 +49,7 @@ $showNavLinks = !$hasHeaderTabs && !empty($navLinks);
<a href="<?= htmlspecialchars($appBaseUrl . '/admin/profile.php') ?>" class="user-menu-item" data-menu="profile">Profil</a>
<a href="<?= htmlspecialchars($appBaseUrl . '/admin/dashboard.php') ?>" class="user-menu-item" data-role="admin">Dashboard</a>
<a href="<?= htmlspecialchars($appBaseUrl . '/admin/settings.php') ?>" class="user-menu-item" data-role="admin">API & Tabellen</a>
<a href="<?= htmlspecialchars($appBaseUrl . '/admin/users.php') ?>" class="user-menu-item" data-role="owner">Userverwaltung</a>
<button id="btn-logout" type="button" class="user-menu-item text-red-600">Logout</button>
</div>
</div>

3
public/admin/users.php Normal file
View File

@@ -0,0 +1,3 @@
<?php
require_once __DIR__ . '/../../config/fileload.php';
require_once __DIR__ . '/../../partials/landingpage/accountsetup/users.php';

View File

@@ -21,7 +21,6 @@ let configExampleBtn;
let configExampleDialog;
let bridgeSetupDialog;
let openBridgeSetupBtn;
let adminLoadBridgeBtn;
let closeBridgeSetupBtn;
export function initBridgeSetupPage() {
@@ -40,7 +39,6 @@ export function initBridgeSetupPage() {
modeInputs = Array.from(form.querySelectorAll('input[name="db_mode"]'));
bridgeSetupDialog = document.getElementById('bridgeSetupDialog');
openBridgeSetupBtn = document.getElementById('btn-open-bridge-setup');
adminLoadBridgeBtn = document.getElementById('btn-admin-load-bridge');
closeBridgeSetupBtn = document.getElementById('btn-close-bridge-setup');
form.addEventListener('submit', submitBridgeSetup);
@@ -59,12 +57,6 @@ export function initBridgeSetupPage() {
closeBridgeSetupBtn?.addEventListener('click', () => {
if (bridgeSetupDialog?.open) bridgeSetupDialog.close();
});
adminLoadBridgeBtn?.addEventListener('click', (ev) => {
if (bridgeSetupDialog?.showModal && !bridgeSetupDialog.open) {
bridgeSetupDialog.showModal();
}
loadTablesFromBridge(ev, { preserveSelection: state.selectedTables.length > 0 });
});
modeInputs.forEach(input => {
input.addEventListener('change', () => applyModeVisibility(input.value));
});

View File

@@ -40,6 +40,7 @@ let adminTablesAllSelect;
let adminTablesSelectedSelect;
let adminTablesAddBtn;
let adminTablesRemoveBtn;
let adminLoadBridgeBtn;
ensureConsoleCapture();
@@ -69,6 +70,7 @@ export function initAccountPage() {
adminTablesSelectedSelect = document.getElementById('adminBridgeTablesSelected');
adminTablesAddBtn = document.getElementById('adminBridgeTablesAdd');
adminTablesRemoveBtn = document.getElementById('adminBridgeTablesRemove');
adminLoadBridgeBtn = document.getElementById('btn-admin-load-bridge');
document.getElementById('btn-user-add')?.addEventListener('click', () => openUserForm());
document.getElementById('userFormCancel')?.addEventListener('click', () => closeUserForm());
@@ -112,6 +114,9 @@ export function initAccountPage() {
adminTablesRemoveBtn?.addEventListener('click', () => {
removeAdminTables(getSelectedOptions(adminTablesSelectedSelect));
});
adminLoadBridgeBtn?.addEventListener('click', () => {
refreshBridgeTablesFromEndpoint();
});
window.addEventListener('bridge-setup-updated', (ev) => {
const setup = ev?.detail || {};
@@ -413,6 +418,32 @@ function addAdminTables(list) {
updateAdminTableSelects(whitelist, merged);
}
async function refreshBridgeTablesFromEndpoint() {
if (state.loading) return;
state.loading = true;
try {
const res = await apiAction('account.bridge.test', { method: 'POST', data: {} });
if (!res?.ok) throw new Error(res?.error || 'Bridge konnte nicht abgefragt werden');
const fetched = normalizeTableList(res.tables || []);
if (!fetched.length) {
toast('Keine Tabellen vom Bridge-Endpunkt erhalten', false);
return;
}
const selected = normalizeTableList(state.settings.bridge_tables || []);
const selectedSet = new Set(selected);
const nextSelected = fetched.filter(name => selectedSet.has(name));
state.settings.bridge_setup = state.settings.bridge_setup || {};
state.settings.bridge_setup.tables = fetched;
state.settings.bridge_tables = nextSelected;
updateAdminTableSelects(fetched, nextSelected);
toast('Tabellen aktualisiert', true);
} catch (err) {
toast(err.message || 'Bridge konnte nicht geprüft werden', false);
} finally {
state.loading = false;
}
}
function removeAdminTables(list) {
const whitelist = normalizeTableList(state.settings.bridge_setup?.tables || []);
if (!whitelist.length) return;