219 lines
5.9 KiB
Plaintext
219 lines
5.9 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<title><%= title %></title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
|
<style>
|
|
*, *::before, *::after { box-sizing: border-box; }
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
background: #f0f2f5;
|
|
padding: 40px 20px;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: center;
|
|
}
|
|
.card {
|
|
width: 100%;
|
|
max-width: 580px;
|
|
background: white;
|
|
padding: 32px;
|
|
border-radius: 14px;
|
|
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
|
|
}
|
|
.card h2 {
|
|
margin: 0 0 6px 0;
|
|
font-size: 22px;
|
|
color: #111827;
|
|
}
|
|
.card p {
|
|
margin: 0 0 24px 0;
|
|
color: #6b7280;
|
|
font-size: 14px;
|
|
}
|
|
.badge-update {
|
|
display: inline-block;
|
|
background: #fef3c7;
|
|
color: #92400e;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
padding: 3px 10px;
|
|
border-radius: 20px;
|
|
margin-bottom: 16px;
|
|
border: 1px solid #fcd34d;
|
|
}
|
|
label {
|
|
display: block;
|
|
margin-top: 16px;
|
|
margin-bottom: 5px;
|
|
font-weight: 600;
|
|
font-size: 13px;
|
|
color: #374151;
|
|
}
|
|
input {
|
|
width: 100%;
|
|
padding: 10px 12px;
|
|
border-radius: 8px;
|
|
border: 1px solid #d1d5db;
|
|
font-size: 14px;
|
|
outline: none;
|
|
transition: border-color 0.2s;
|
|
}
|
|
input:focus {
|
|
border-color: #2563eb;
|
|
box-shadow: 0 0 0 3px rgba(37,99,235,0.12);
|
|
}
|
|
.row {
|
|
display: flex;
|
|
gap: 12px;
|
|
}
|
|
.row > div { flex: 1; }
|
|
.btn-row {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-top: 24px;
|
|
flex-wrap: wrap;
|
|
}
|
|
button {
|
|
padding: 10px 18px;
|
|
border: 0;
|
|
border-radius: 10px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
transition: opacity 0.2s;
|
|
}
|
|
button:hover { opacity: 0.88; }
|
|
.btn-primary { background: #2563eb; color: white; flex: 1; }
|
|
.btn-secondary { background: #111827; color: white; }
|
|
.msg {
|
|
margin-top: 14px;
|
|
padding: 12px 14px;
|
|
border-radius: 10px;
|
|
font-size: 14px;
|
|
display: none;
|
|
}
|
|
.msg.ok { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
|
|
.msg.bad { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }
|
|
.msg.pending { background: #eff6ff; color: #1d4ed8; border: 1px solid #93c5fd; }
|
|
.divider {
|
|
border: none;
|
|
border-top: 1px solid #e5e7eb;
|
|
margin: 24px 0;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="card">
|
|
<h2>🛠️ <%= title %></h2>
|
|
|
|
<% if (typeof isUpdate !== 'undefined' && isUpdate) { %>
|
|
<span class="badge-update">⚠️ Bestehende Konfiguration wird überschrieben</span>
|
|
<% } %>
|
|
|
|
<p>DB-Verbindungsdaten eingeben. Die Verbindung wird vor dem Speichern geprüft.</p>
|
|
|
|
<form method="POST" action="/setup" id="setupForm">
|
|
|
|
<div class="row">
|
|
<div>
|
|
<label for="host">DB Host</label>
|
|
<input
|
|
id="host"
|
|
name="host"
|
|
placeholder="85.215.63.122"
|
|
value="<%= defaults.host %>"
|
|
required
|
|
/>
|
|
</div>
|
|
<div style="max-width:110px">
|
|
<label for="port">Port</label>
|
|
<input
|
|
id="port"
|
|
name="port"
|
|
placeholder="3306"
|
|
value="<%= defaults.port %>"
|
|
required
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<label for="user">DB Benutzer</label>
|
|
<input
|
|
id="user"
|
|
name="user"
|
|
placeholder="praxisuser"
|
|
value="<%= defaults.user %>"
|
|
required
|
|
/>
|
|
|
|
<label for="password">DB Passwort</label>
|
|
<input
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
placeholder="<%= typeof isUpdate !== 'undefined' && isUpdate ? '(unverändert lassen = leer lassen)' : '' %>"
|
|
/>
|
|
|
|
<label for="name">DB Name</label>
|
|
<input
|
|
id="name"
|
|
name="name"
|
|
placeholder="praxissoftware"
|
|
value="<%= defaults.name %>"
|
|
required
|
|
/>
|
|
|
|
<hr class="divider" />
|
|
|
|
<div class="btn-row">
|
|
<button type="button" class="btn-secondary" onclick="testConnection()">
|
|
🔍 Verbindung testen
|
|
</button>
|
|
<button type="submit" class="btn-primary">
|
|
✅ Speichern & abschließen
|
|
</button>
|
|
</div>
|
|
|
|
<div id="msg" class="msg"></div>
|
|
</form>
|
|
</div>
|
|
|
|
<script>
|
|
async function testConnection() {
|
|
const msg = document.getElementById("msg");
|
|
msg.className = "msg pending";
|
|
msg.style.display = "block";
|
|
msg.textContent = "⏳ Teste Verbindung...";
|
|
|
|
// Felder einzeln auslesen (sicherer als FormData bei doppelten Namen)
|
|
const body = {
|
|
host: document.getElementById("host").value.trim(),
|
|
port: document.getElementById("port").value.trim(),
|
|
user: document.getElementById("user").value.trim(),
|
|
password: document.getElementById("password").value,
|
|
name: document.getElementById("name").value.trim(),
|
|
};
|
|
|
|
try {
|
|
const res = await fetch("/setup/test", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(body),
|
|
});
|
|
|
|
const json = await res.json();
|
|
msg.className = "msg " + (json.ok ? "ok" : "bad");
|
|
msg.textContent = json.message;
|
|
} catch (e) {
|
|
msg.className = "msg bad";
|
|
msg.textContent = "❌ Netzwerkfehler: " + e.message;
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|