264 lines
9.6 KiB
Plaintext
264 lines
9.6 KiB
Plaintext
<div class="layout">
|
||
|
||
<!-- ✅ SIDEBAR (wie Dashboard, aber Admin Sidebar) -->
|
||
<%- include("../partials/admin-sidebar", { user, active: "database", lang }) %>
|
||
|
||
<!-- ✅ MAIN -->
|
||
<div class="main">
|
||
|
||
<!-- ✅ HEADER (wie Dashboard) -->
|
||
<%- include("../partials/page-header", {
|
||
user,
|
||
title: "Datenbankverwaltung",
|
||
subtitle: "",
|
||
showUserName: true,
|
||
hideDashboardButton: true
|
||
}) %>
|
||
|
||
<div class="content p-4">
|
||
|
||
<!-- Flash Messages -->
|
||
<%- include("../partials/flash") %>
|
||
|
||
<div class="container-fluid p-0">
|
||
<div class="row g-3">
|
||
|
||
<!-- ✅ DB Konfiguration -->
|
||
<div class="col-12">
|
||
<div class="card shadow mb-3">
|
||
<div class="card-body">
|
||
|
||
<h4 class="mb-3">
|
||
<i class="bi bi-sliders"></i> Datenbank Konfiguration
|
||
</h4>
|
||
|
||
<p class="text-muted mb-4">
|
||
Hier kannst du die DB-Verbindung testen und speichern.
|
||
</p>
|
||
|
||
<!-- ✅ TEST + SPEICHERN -->
|
||
<form method="POST" action="/admin/database/test" class="row g-3 mb-3" autocomplete="off">
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label">Host / IP</label>
|
||
<input
|
||
type="text"
|
||
name="host"
|
||
class="form-control"
|
||
value="<%= (typeof dbConfig !== 'undefined' && dbConfig && dbConfig.host) ? dbConfig.host : '' %>"
|
||
autocomplete="off"
|
||
required
|
||
>
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label">Port</label>
|
||
<input
|
||
type="number"
|
||
name="port"
|
||
class="form-control"
|
||
value="<%= (typeof dbConfig !== 'undefined' && dbConfig && dbConfig.port) ? dbConfig.port : 3306 %>"
|
||
autocomplete="off"
|
||
required
|
||
>
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label">Datenbank</label>
|
||
<input
|
||
type="text"
|
||
name="name"
|
||
class="form-control"
|
||
value="<%= (typeof dbConfig !== 'undefined' && dbConfig && dbConfig.name) ? dbConfig.name : '' %>"
|
||
autocomplete="off"
|
||
required
|
||
>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label">Benutzer</label>
|
||
<input
|
||
type="text"
|
||
name="user"
|
||
class="form-control"
|
||
value="<%= (typeof dbConfig !== 'undefined' && dbConfig && dbConfig.user) ? dbConfig.user : '' %>"
|
||
autocomplete="off"
|
||
required
|
||
>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label">Passwort</label>
|
||
<input
|
||
type="password"
|
||
name="password"
|
||
class="form-control"
|
||
value="<%= (typeof dbConfig !== 'undefined' && dbConfig && dbConfig.password) ? dbConfig.password : '' %>"
|
||
autocomplete="off"
|
||
required
|
||
>
|
||
</div>
|
||
|
||
<div class="col-12 d-flex flex-wrap gap-2">
|
||
|
||
<button type="submit" class="btn btn-outline-primary">
|
||
<i class="bi bi-plug"></i> Verbindung testen
|
||
</button>
|
||
|
||
<button
|
||
type="submit"
|
||
class="btn btn-success"
|
||
formaction="/admin/database"
|
||
>
|
||
<i class="bi bi-save"></i> Speichern
|
||
</button>
|
||
|
||
</div>
|
||
</form>
|
||
|
||
<% if (typeof testResult !== "undefined" && testResult) { %>
|
||
<div class="alert <%= testResult.ok ? 'alert-success' : 'alert-danger' %> mb-0">
|
||
<%= testResult.message %>
|
||
</div>
|
||
<% } %>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ✅ System Info -->
|
||
<div class="col-12">
|
||
<div class="card shadow mb-3">
|
||
<div class="card-body">
|
||
|
||
<h4 class="mb-3">
|
||
<i class="bi bi-info-circle"></i> Systeminformationen
|
||
</h4>
|
||
|
||
<% if (typeof systemInfo !== "undefined" && systemInfo && systemInfo.error) { %>
|
||
|
||
<div class="alert alert-danger mb-0">
|
||
❌ Fehler beim Auslesen der Datenbankinfos:
|
||
<div class="mt-2"><code><%= systemInfo.error %></code></div>
|
||
</div>
|
||
|
||
<% } else if (typeof systemInfo !== "undefined" && systemInfo) { %>
|
||
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<div class="border rounded p-3 h-100">
|
||
<div class="text-muted small">MySQL Version</div>
|
||
<div class="fw-bold"><%= systemInfo.version %></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<div class="border rounded p-3 h-100">
|
||
<div class="text-muted small">Anzahl Tabellen</div>
|
||
<div class="fw-bold"><%= systemInfo.tableCount %></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<div class="border rounded p-3 h-100">
|
||
<div class="text-muted small">Datenbankgröße</div>
|
||
<div class="fw-bold"><%= systemInfo.dbSizeMB %> MB</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<% if (systemInfo.tables && systemInfo.tables.length > 0) { %>
|
||
<hr>
|
||
|
||
<h6 class="mb-2">Tabellenübersicht</h6>
|
||
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-bordered table-hover align-middle">
|
||
<thead class="table-dark">
|
||
<tr>
|
||
<th>Tabelle</th>
|
||
<th class="text-end">Zeilen</th>
|
||
<th class="text-end">Größe (MB)</th>
|
||
</tr>
|
||
</thead>
|
||
|
||
<tbody>
|
||
<% systemInfo.tables.forEach(t => { %>
|
||
<tr>
|
||
<td><%= t.name %></td>
|
||
<td class="text-end"><%= t.row_count %></td>
|
||
<td class="text-end"><%= t.size_mb %></td>
|
||
</tr>
|
||
<% }) %>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<% } %>
|
||
|
||
<% } else { %>
|
||
|
||
<div class="alert alert-warning mb-0">
|
||
⚠️ Keine Systeminfos verfügbar (DB ist evtl. nicht konfiguriert oder Verbindung fehlgeschlagen).
|
||
</div>
|
||
|
||
<% } %>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ✅ Backup & Restore -->
|
||
<div class="col-12">
|
||
<div class="card shadow">
|
||
<div class="card-body">
|
||
|
||
<h4 class="mb-3">
|
||
<i class="bi bi-hdd-stack"></i> Backup & Restore
|
||
</h4>
|
||
|
||
<div class="d-flex flex-wrap gap-3">
|
||
|
||
<!-- ✅ Backup erstellen -->
|
||
<form action="/admin/database/backup" method="POST">
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="bi bi-download"></i> Backup erstellen
|
||
</button>
|
||
</form>
|
||
|
||
<!-- ✅ Restore auswählen -->
|
||
<form action="/admin/database/restore" method="POST">
|
||
<div class="input-group">
|
||
|
||
<select name="backupFile" class="form-select" required>
|
||
<option value="">Backup auswählen...</option>
|
||
|
||
<% (typeof backupFiles !== "undefined" && backupFiles ? backupFiles : []).forEach(file => { %>
|
||
<option value="<%= file %>"><%= file %></option>
|
||
<% }) %>
|
||
</select>
|
||
|
||
<button type="submit" class="btn btn-warning">
|
||
<i class="bi bi-upload"></i> Restore starten
|
||
</button>
|
||
</div>
|
||
</form>
|
||
|
||
</div>
|
||
|
||
<% if (typeof backupFiles === "undefined" || !backupFiles || backupFiles.length === 0) { %>
|
||
<div class="alert alert-secondary mt-3 mb-0">
|
||
ℹ️ Noch keine Backups vorhanden.
|
||
</div>
|
||
<% } %>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|