390 lines
21 KiB
PHP
Executable File
390 lines
21 KiB
PHP
Executable File
<?php
|
||
$pageTitle = 'Email Template System – API & Tabellen';
|
||
$pageId = 'admin';
|
||
$navActive = 'settings';
|
||
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="admin">
|
||
<div class="flex items-center justify-between mb-3">
|
||
<h4>Absender für Testmails</h4>
|
||
<button type="button" id="btn-sender-add" class="btn">+ Absender</button>
|
||
</div>
|
||
<div class="overflow-auto">
|
||
<table class="team-table" id="senderTable">
|
||
<thead>
|
||
<tr><th>Bezeichnung</th><th>From-Name</th><th>E-Mail</th><th>Reply-To</th><th class="text-right">Aktionen</th></tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
<form id="senderForm" class="space-y-3 mt-4 hidden">
|
||
<input type="hidden" name="sender_id">
|
||
<label class="block text-sm text-slate-600">Bezeichnung
|
||
<input type="text" name="label" class="input mt-1" placeholder="Interner Name (optional)">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Absender-Name
|
||
<input type="text" name="from_name" class="input mt-1" placeholder="z.B. Newsletter Team">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Absender-E-Mail
|
||
<input type="email" name="from_email" class="input mt-1" required placeholder="news@example.com">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Reply-To (optional)
|
||
<input type="email" name="reply_to" class="input mt-1" placeholder="support@example.com">
|
||
</label>
|
||
<div class="flex justify-end gap-2">
|
||
<button type="button" id="senderFormCancel" 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>Versandprofile (SMTP)</h4>
|
||
<button type="button" id="btn-smtp-profile-add" class="btn">+ Versandprofil</button>
|
||
</div>
|
||
<p class="text-sm text-slate-600 mb-3">Mehrere SMTP-Profile fuer unterschiedliche Absender oder Server.</p>
|
||
<div class="overflow-auto">
|
||
<table class="team-table" id="smtpProfileTable">
|
||
<thead>
|
||
<tr><th>Bezeichnung</th><th>Server</th><th>Benutzer</th><th>Absender</th><th class="text-right">Aktionen</th></tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
<form id="smtpProfileForm" class="space-y-3 mt-4 hidden">
|
||
<input type="hidden" name="profile_id">
|
||
<label class="block text-sm text-slate-600">Bezeichnung
|
||
<input type="text" name="label" class="input mt-1" placeholder="Profil-Name">
|
||
</label>
|
||
<div class="grid md:grid-cols-2 gap-3">
|
||
<label class="block text-sm text-slate-600">SMTP-Server
|
||
<input type="text" name="smtp_host" class="input mt-1" placeholder="smtp.example.com">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Port
|
||
<input type="number" name="smtp_port" class="input mt-1" placeholder="587">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Verschluesselung
|
||
<select name="smtp_secure" class="input mt-1">
|
||
<option value="">Keine</option>
|
||
<option value="tls">TLS</option>
|
||
<option value="ssl">SSL</option>
|
||
</select>
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Benutzername
|
||
<input type="text" name="smtp_user" class="input mt-1" placeholder="user@example.com">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Passwort
|
||
<input type="password" name="smtp_pass" class="input mt-1" placeholder="••••••••">
|
||
</label>
|
||
<label class="inline-flex items-center gap-2 text-xs text-slate-500 mt-6">
|
||
<input type="checkbox" name="smtp_pass_clear" value="1"> Passwort loeschen
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Absender (E-Mail)
|
||
<input type="email" name="from_email" class="input mt-1" placeholder="no-reply@example.com">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Absender (Name)
|
||
<input type="text" name="from_name" class="input mt-1" placeholder="EmailTemplate">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Reply-To (optional)
|
||
<input type="email" name="reply_to" class="input mt-1" placeholder="support@example.com">
|
||
</label>
|
||
</div>
|
||
<div class="flex justify-end gap-2">
|
||
<button type="button" id="smtpProfileFormCancel" class="btn">Abbrechen</button>
|
||
<button type="submit" class="btn">Speichern</button>
|
||
</div>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="section-card" data-role="admin">
|
||
<h4>Integrationen, Downloads & Tokens</h4>
|
||
<p class="text-sm text-slate-600 mb-4">Die Dateien enthalten automatisch deine aktuellen Tokens. Nach dem Speichern neuer Tokens bitte die Dateien erneut herunterladen.</p>
|
||
<form id="settingsForm" class="space-y-3">
|
||
<label class="block text-sm text-slate-600">Bridge-URL
|
||
<input type="url" name="bridge_url" class="input mt-1" placeholder="https://domain.tld/emailtemplate_bridge.php">
|
||
</label>
|
||
<div>
|
||
<label class="block text-sm text-slate-600">Bridge Token</label>
|
||
<div class="flex gap-2 mt-1">
|
||
<input type="text" name="bridge_token" class="input" readonly>
|
||
<button type="button" class="btn" data-rotate="bridge">Neu erstellen</button>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm text-slate-600">Sender Token</label>
|
||
<div class="flex gap-2 mt-1">
|
||
<input type="text" name="sender_token" class="input" readonly>
|
||
<button type="button" class="btn" data-rotate="sender">Neu erstellen</button>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm text-slate-600">Externer API-Token</label>
|
||
<div class="flex gap-2 mt-1">
|
||
<input type="text" name="external_api_token" class="input" readonly>
|
||
<button type="button" class="btn" data-rotate="external">Neu erstellen</button>
|
||
</div>
|
||
</div>
|
||
<fieldset class="border border-slate-200 rounded-xl p-4">
|
||
<legend class="px-2 text-sm font-semibold">SMTP-Versand</legend>
|
||
<p class="text-xs text-slate-500 mb-3">Diese Zugangsdaten werden fuer den Testversand genutzt, wenn SMTP aktiviert ist.</p>
|
||
<div class="flex items-center justify-between gap-3 mb-3">
|
||
<label class="inline-flex items-center gap-2 text-sm text-slate-600">
|
||
<input type="checkbox" name="smtp_enabled" value="1"> SMTP aktivieren
|
||
</label>
|
||
<button type="button" id="btn-smtp-test" class="btn">SMTP Test</button>
|
||
</div>
|
||
<div class="grid md:grid-cols-2 gap-3">
|
||
<label class="block text-sm text-slate-600">SMTP-Server
|
||
<input type="text" name="smtp_host" class="input mt-1" placeholder="smtp.example.com">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Port
|
||
<input type="number" name="smtp_port" class="input mt-1" placeholder="587">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Verschluesselung
|
||
<select name="smtp_secure" class="input mt-1">
|
||
<option value="">Keine</option>
|
||
<option value="tls">TLS</option>
|
||
<option value="ssl">SSL</option>
|
||
</select>
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Benutzername
|
||
<input type="text" name="smtp_user" class="input mt-1" placeholder="user@example.com">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Passwort
|
||
<input type="password" name="smtp_pass" class="input mt-1" placeholder="••••••••">
|
||
</label>
|
||
<label class="inline-flex items-center gap-2 text-xs text-slate-500 mt-6">
|
||
<input type="checkbox" name="smtp_pass_clear" value="1"> Passwort loeschen
|
||
</label>
|
||
<label class="block text-sm text-slate-600">SMTP-Absender (E-Mail)
|
||
<input type="email" name="smtp_from_email" class="input mt-1" placeholder="no-reply@example.com">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">SMTP-Absender (Name)
|
||
<input type="text" name="smtp_from_name" class="input mt-1" placeholder="EmailTemplate">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Reply-To (optional)
|
||
<input type="email" name="smtp_reply_to" class="input mt-1" placeholder="support@example.com">
|
||
</label>
|
||
</div>
|
||
</fieldset>
|
||
<div class="flex justify-between gap-2 flex-wrap pt-2">
|
||
<div class="flex gap-2" data-role="admin">
|
||
<button type="button" class="btn" data-download="bridge">Bridge-Datei</button>
|
||
<button type="button" class="btn" data-download="sender">Sender-Datei</button>
|
||
</div>
|
||
<button type="submit" class="btn ms-auto">Einstellungen speichern</button>
|
||
</div>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="section-card" data-role="admin">
|
||
<div class="flex items-center justify-between flex-wrap gap-3 mb-3">
|
||
<div>
|
||
<h4>Bridge-Datei & Tabellenfreigaben</h4>
|
||
<p class="text-sm text-slate-600">Die Bridge-Konfiguration dient ausschliesslich der Erstellung der Bridge-Datei und steuert, welche Tabellen dort freigegeben sind.</p>
|
||
</div>
|
||
<div class="flex gap-2 flex-wrap">
|
||
<button type="button" id="btn-open-bridge-setup" class="btn">Bridge-Setup oeffnen</button>
|
||
<button type="button" id="btn-admin-load-bridge" class="btn">Tabellen neu laden</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grid md:grid-cols-[1fr_auto_1fr] gap-3">
|
||
<div>
|
||
<p class="text-xs text-slate-500 mb-1">Freigegebene Tabellen (Bridge-Datei)</p>
|
||
<select id="adminBridgeTablesAll" class="input" size="8" multiple></select>
|
||
</div>
|
||
<div class="flex flex-col gap-2 justify-center">
|
||
<button type="button" id="adminBridgeTablesAdd" class="btn" aria-label="Zur Placeholder-Auswahl hinzufuegen">→</button>
|
||
<button type="button" id="adminBridgeTablesRemove" class="btn" aria-label="Aus Placeholder-Auswahl entfernen">←</button>
|
||
</div>
|
||
<div>
|
||
<p class="text-xs text-slate-500 mb-1">Tabellen fuer Placeholder-Auswahl</p>
|
||
<select id="adminBridgeTablesSelected" class="input" size="8" multiple></select>
|
||
</div>
|
||
</div>
|
||
<p class="text-xs text-slate-500 mt-2">Nur diese Tabellen erscheinen spaeter bei der Placeholder-Auswahl.</p>
|
||
<div class="flex justify-end mt-3">
|
||
<button type="submit" form="settingsForm" class="btn">Einstellungen speichern</button>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<div id="toast-root"></div>
|
||
|
||
<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>
|
||
</div>
|
||
<div class="space-y-4">
|
||
<p class="text-sm text-slate-600">
|
||
Diese Angaben werden nur verwendet, um die <strong>emailtemplate_bridge.php</strong> zu generieren. Das EmailTemplate-System selbst behält Zugriff auf alle Tabellen; die hier definierten Whitelists greifen ausschliesslich in der Bridge-Datei.
|
||
</p>
|
||
<form id="bridgeSetupForm" class="space-y-4">
|
||
<div>
|
||
<label class="block text-sm text-slate-600">Tabellen-Whitelist (Bridge-Datei)</label>
|
||
<div class="grid md:grid-cols-[1fr_auto_1fr] gap-3 mt-2">
|
||
<div>
|
||
<p class="text-xs text-slate-500 mb-1">Alle Tabellen (Bridge-Endpunkt)</p>
|
||
<select id="bridgeTablesAll" class="input" size="8" multiple></select>
|
||
</div>
|
||
<div class="flex flex-col gap-2 justify-center">
|
||
<button type="button" id="bridgeTablesAdd" class="btn" aria-label="Zur Whitelist hinzufuegen">→</button>
|
||
<button type="button" id="bridgeTablesRemove" class="btn" aria-label="Aus Whitelist entfernen">←</button>
|
||
</div>
|
||
<div>
|
||
<p class="text-xs text-slate-500 mb-1">Whitelist fuer Bridge-Datei</p>
|
||
<select id="bridgeTablesSelected" class="input" size="8" multiple></select>
|
||
</div>
|
||
</div>
|
||
<p class="text-xs text-slate-500 mt-2">Die Auswahl bestimmt, welche Tabellen in der Bridge-Datei erlaubt sind.</p>
|
||
</div>
|
||
|
||
<fieldset class="border border-slate-200 rounded-xl p-4">
|
||
<legend class="px-2 text-sm font-semibold">Datenbankquelle</legend>
|
||
<p class="text-xs text-slate-500 mb-3">Die Auswahl bestimmt, welche Werte in die Bridge-Datei geschrieben werden.</p>
|
||
<div class="flex flex-wrap gap-4 text-sm text-slate-600 mb-3">
|
||
<label class="inline-flex items-center gap-2">
|
||
<input type="radio" name="db_mode" value="direct" checked> Direkte Angaben (Host, DB, Benutzer …)
|
||
</label>
|
||
<label class="inline-flex items-center gap-2">
|
||
<input type="radio" name="db_mode" value="config"> Aus bestehender Konfigurationsdatei laden
|
||
</label>
|
||
</div>
|
||
|
||
<div id="directFields" class="grid md:grid-cols-2 gap-3">
|
||
<label class="block text-sm text-slate-600">Server / Host
|
||
<input type="text" name="direct_host" class="input mt-1" placeholder="127.0.0.1">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Port
|
||
<input type="number" name="direct_port" class="input mt-1" placeholder="3306">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Datenbankname
|
||
<input type="text" name="direct_database" class="input mt-1" placeholder="kunden_db">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Zeichensatz
|
||
<input type="text" name="direct_charset" class="input mt-1" value="utf8mb4">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Benutzername
|
||
<input type="text" name="direct_user" class="input mt-1" placeholder="db_user">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Passwort
|
||
<input type="text" name="direct_password" class="input mt-1" placeholder="••••">
|
||
</label>
|
||
</div>
|
||
|
||
<div id="configFields" class="hidden space-y-3">
|
||
<div>
|
||
<label class="block text-sm text-slate-600">Pfad zur Konfigurationsdatei</label>
|
||
<input type="text" name="config_file" class="input mt-1" placeholder="../config/database.php">
|
||
<p class="text-xs text-slate-500 mt-1">Relativ zur Bridge-Datei oder absolut. Die Datei sollte ein Array oder Objekt mit den Zugangsdaten liefern.</p>
|
||
<button type="button" id="btn-config-example" class="btn mt-2 text-xs" data-role="admin">Beispiel: Array-Mapping</button>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm text-slate-600">Basis-Pfad im Array (optional)</label>
|
||
<input type="text" name="config_base" class="input mt-1" placeholder="database.connections.mysql">
|
||
<p class="text-xs text-slate-500 mt-1">Dot-Notation, um in verschachtelte Arrays zu springen.</p>
|
||
</div>
|
||
<div class="grid md:grid-cols-2 gap-3">
|
||
<label class="block text-sm text-slate-600">Host-Key
|
||
<input type="text" name="config_host_key" class="input mt-1" placeholder="host">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Port-Key
|
||
<input type="text" name="config_port_key" class="input mt-1" placeholder="port">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">DB-Name-Key
|
||
<input type="text" name="config_database_key" class="input mt-1" placeholder="database">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Charset-Key
|
||
<input type="text" name="config_charset_key" class="input mt-1" placeholder="charset">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">User-Key
|
||
<input type="text" name="config_user_key" class="input mt-1" placeholder="username">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Passwort-Key
|
||
<input type="text" name="config_password_key" class="input mt-1" placeholder="password">
|
||
</label>
|
||
</div>
|
||
<p class="text-xs text-slate-500">Alle Keys nutzen Dot-Notation relativ zum Basis-Pfad.</p>
|
||
</div>
|
||
</fieldset>
|
||
|
||
<div class="flex flex-wrap gap-2 items-center">
|
||
<button type="button" id="btn-load-remote" class="btn" data-role="admin">Tabellen vom Bridge-Endpunkt laden</button>
|
||
<span class="text-xs text-slate-500">Nutzt Bridge-URL/Token aus den Einstellungen und uebernimmt optional DB-Settings aus der Bridge-Datei.</span>
|
||
<button type="submit" class="btn">Bridge-Setup speichern</button>
|
||
</div>
|
||
<div id="setupStatus" class="text-xs text-slate-500">Noch nicht gespeichert.</div>
|
||
</form>
|
||
|
||
<div class="border-t border-slate-200 pt-4">
|
||
<h4 class="text-base font-semibold mb-2">Schriftarten (optional)</h4>
|
||
<p class="text-sm text-slate-600 mb-3">
|
||
Eigene Fonts vom Hoster: gib einen lokalen Schriftarten-Ordner (plus oeffentliche URL) an
|
||
oder trage direkte Font-URLs ein. Das System erstellt @font-face automatisch und zeigt die
|
||
Fonts im Editor an.
|
||
</p>
|
||
<div id="bridgeFontsForm" class="space-y-3">
|
||
<label class="block text-sm text-slate-600">Schriftarten-Ordner (Serverpfad, optional)
|
||
<input type="text" name="fonts_dir" class="input mt-1" placeholder="/var/www/site/public/fonts">
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Oeffentliche Basis-URL zum Ordner
|
||
<input type="text" name="fonts_url_base" class="input mt-1" placeholder="https://deine-seite.de/fonts">
|
||
<p class="text-xs text-slate-500 mt-1">Wird genutzt, um die Dateien im Editor/Email zu laden.</p>
|
||
</label>
|
||
<label class="block text-sm text-slate-600">Direkte Font-URLs (eine pro Zeile, optional)
|
||
<textarea name="fonts_urls" class="input mt-1 h-28" placeholder="Family|https://deine-seite.de/fonts/MyFont.woff2"></textarea>
|
||
<p class="text-xs text-slate-500 mt-1">
|
||
Format: <code>Family|URL</code> oder nur <code>URL</code>. Erlaubte Endungen: woff2, woff, ttf, otf.
|
||
</p>
|
||
</label>
|
||
<p class="text-xs text-slate-500">
|
||
Hinweis: woff2/woff ist empfohlen, ttf/otf funktioniert meist, wird aber nicht von allen Mail-Clients geladen.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="configExampleDialog" class="rounded-xl max-w-2xl w-[90vw]">
|
||
<form method="dialog" class="space-y-3">
|
||
<h3 class="text-lg font-semibold">Beispiel: Mapping einer Config-Datei</h3>
|
||
<p class="text-sm text-slate-600">Angenommen, deine <code>../config/database.php</code> liefert folgendes Array:</p>
|
||
<pre class="bg-slate-900 text-slate-100 text-xs p-3 rounded-lg overflow-auto"><?php echo htmlspecialchars(<<<'PHP'
|
||
<?php
|
||
return [
|
||
'database' => [
|
||
'connections' => [
|
||
'default' => [
|
||
'host' => '127.0.0.1',
|
||
'port' => 3306,
|
||
'database' => 'kunden_db',
|
||
'username' => 'dbuser',
|
||
'password' => 'secret',
|
||
'charset' => 'utf8mb4',
|
||
],
|
||
],
|
||
],
|
||
];
|
||
PHP, ENT_QUOTES); ?></pre>
|
||
<p class="text-sm text-slate-600">Dann trägst du ein:</p>
|
||
<ul class="text-sm text-slate-700 list-disc ps-5">
|
||
<li><strong>Pfad zur Konfigurationsdatei:</strong> <code>../config/database.php</code></li>
|
||
<li><strong>Basis-Pfad:</strong> <code>database.connections.default</code></li>
|
||
<li><strong>Host-/Port-/DB-/User-/Pass-/Charset-Key:</strong> jeweils <code>host</code>, <code>port</code>, <code>database</code>, <code>username</code>, <code>password</code>, <code>charset</code></li>
|
||
</ul>
|
||
<p class="text-sm text-slate-600">Die Bridge liest dann automatisch die Werte aus diesem Array und baut daraus den DSN.</p>
|
||
<div class="text-right">
|
||
<button type="submit" class="btn">Verstanden</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
<?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';
|