Files
emailtemplate.it/public/index.php
2026-02-09 01:38:39 +01:00

225 lines
10 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . '/../config/fileload.php';
$debugDir = dirname(__DIR__) . '/debug';
if (!is_dir($debugDir)) {
@mkdir($debugDir, 0777, true);
@chmod($debugDir, 0777);
}
$clientIp = '';
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$clientIp = trim(explode(',', (string)$_SERVER['HTTP_X_FORWARDED_FOR'])[0]);
} elseif (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$clientIp = (string)$_SERVER['HTTP_CF_CONNECTING_IP'];
} elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) {
$clientIp = (string)$_SERVER['HTTP_X_REAL_IP'];
} else {
$clientIp = (string)($_SERVER['REMOTE_ADDR'] ?? '');
}
$clientIp = trim($clientIp);
$version = $GLOBALS['app_version'] ?? '';
$versionLabel = $version ? (' | v' . $version) : '';
$accessLine = date(DATE_ATOM) . ' | ' . ($clientIp !== '' ? $clientIp : 'unknown') . $versionLabel . "\n";
debug_log_write('last_access', $accessLine, ['append' => true, 'json' => false]);
$pageTitle = 'Email Template System Admin';
$pageId = 'home';
$navLinks = [];
ob_start();
?>
<nav id="sectionTabs" class="isolate inline-flex flex-wrap rounded-2xl shadow-sm border bg-white overflow-hidden"></nav>
<button id="btn-new" type="button" class="btn">Neu …</button>
<?php
$headerTabs = ob_get_clean();
require __DIR__ . '/../partials/structure/layout_start.php';
?>
<main class="max-w-6xl mx-auto p-4 flex-1 w-full space-y-6">
<header class="pb-2 border-b border-slate-200">
<h1 class="font-semibold text-lg text-slate-900">Email Template System</h1>
<p class="text-sm text-slate-500">Wähle eine Kategorie, um Templates, Sections, Blocks oder Snippets zu pflegen.</p>
</header>
<section id="view-content" class="view"></section>
</main>
<!-- Create Dialog -->
<dialog id="createDialog" class="rounded-2xl p-0 w-[540px]">
<form id="createForm" method="dialog" class="p-4 bg-white rounded-2xl">
<h3 class="text-lg font-semibold mb-2">Neues Element erstellen</h3>
<p id="createHint" class="text-sm text-slate-600 mb-3"></p>
<div class="space-y-3" id="createFields"></div>
<div class="mt-4 flex justify-end gap-2">
<button type="button" id="createCancel" class="btn">Abbrechen</button>
<button type="submit" id="createSubmit" class="btn">Erstellen</button>
</div>
</form>
</dialog>
<!-- Delete Confirm Dialog -->
<dialog id="deleteDialog" class="rounded-2xl p-0 w-[520px]">
<form id="deleteForm" method="dialog" class="p-4 bg-white rounded-2xl">
<h3 class="text-lg font-semibold mb-2">Eintrag löschen?</h3>
<p id="deleteText" class="text-sm text-slate-600 mb-4"></p>
<div class="mt-1 flex justify-end gap-2">
<button type="button" id="deleteCancel" class="btn">Abbrechen</button>
<button type="submit" class="btn btn-danger">Löschen</button>
</div>
</form>
</dialog>
<!-- Editor Dialog -->
<dialog id="editorDialog" class="rounded-2xl p-0 w-[95vw] h-[90vh]">
<div class="h-full flex flex-col">
<div class="px-4 py-2 border-b flex items-center gap-2 bg-white/80 backdrop-blur">
<strong class="me-auto">E-Mail Editor</strong>
<label class="text-xs text-slate-600">Editor</label>
<select id="editorTypeSelect" class="input h-8 py-0 text-sm">
<option value="grapesjs">GrapesJS</option>
<option value="craftjs">Craft.js</option>
</select>
<label class="text-xs text-slate-600">Version</label>
<select id="versionSelect" class="input h-8 py-0 text-sm min-w-[200px]">
<option value="">Letzte Versionen</option>
</select>
<span id="versionActiveBadge" class="hidden text-xs px-2 py-1 rounded-full bg-emerald-100 text-emerald-700">Aktiv</span>
<button id="btn-activate-version" type="button" class="btn">Aktiv setzen</button>
<button id="btn-deactivate-version" type="button" class="btn">Deaktivieren</button>
<button id="btn-clear-main" type="button" class="btn" title="Leeren">🧹</button>
<button id="btn-preview" type="button" class="btn">Vorschau</button>
<button id="btn-test" type="button" class="btn">Testversand</button>
<button id="btn-save" type="button" class="btn">Speichern</button>
<button id="btn-close" type="button" class="btn">Schließen</button>
</div>
<div id="craftEditor" class="hidden flex-1 w-full">
<div id="craftEditorMount" class="w-full h-full"></div>
</div>
<iframe id="editorFrame" src="about:blank" class="flex-1 w-full"></iframe>
</div>
</dialog>
<!-- Preview Dialog -->
<dialog id="previewDialog" class="rounded-2xl p-0 w-[90vw] h-[90vh]">
<div class="h-full flex flex-col">
<div class="px-4 py-2 border-b flex items-center gap-2 bg-white/80 backdrop-blur">
<strong class="me-auto">Vorschau</strong>
<button id="btn-close-preview" type="button" class="btn">Schließen</button>
</div>
<iframe id="previewFrame" class="flex-1 w-full"></iframe>
</div>
</dialog>
<!-- Test Send Dialog -->
<dialog id="sendTestDialog" class="rounded-2xl p-0 w-[480px]">
<form id="sendTestForm" method="dialog" class="p-4 bg-white rounded-2xl space-y-4">
<h3 class="text-lg font-semibold">Testversand</h3>
<p id="send_template_info" class="text-sm text-slate-600">Kein Template ausgewählt.</p>
<label class="block">
<span class="text-sm text-slate-600">Empfänger (E-Mail)</span>
<input id="send_to" type="email" required class="mt-1 w-full border rounded-lg px-3 py-2" placeholder="name@example.com" />
</label>
<label class="block">
<span class="text-sm text-slate-600">Betreff</span>
<input id="send_subject" type="text" class="mt-1 w-full border rounded-lg px-3 py-2" value="Testversand" />
</label>
<label class="block">
<span class="text-sm text-slate-600">Absender</span>
<select id="send_sender" class="mt-1 w-full border rounded-lg px-3 py-2">
<option value="">Standard (System)</option>
</select>
<p id="send_sender_hint" class="text-xs text-slate-500 mt-1 hidden">Keine individuellen Absender gefunden. Lege sie unter „Mein Konto“ an.</p>
</label>
<div class="flex justify-end gap-2">
<button type="button" id="btn-cancel-send" class="btn">Abbrechen</button>
<button type="submit" id="btn-send-now" class="btn">Senden</button>
</div>
</form>
</dialog>
<dialog id="unsavedDialog" class="rounded-2xl p-0 w-[440px]">
<div class="p-4 bg-white rounded-2xl space-y-4">
<h3 class="text-lg font-semibold">Ungespeicherte Änderungen</h3>
<p class="text-sm text-slate-600">Es gibt ungespeicherte Änderungen. Möchtest du diese speichern?</p>
<div class="flex justify-end gap-2">
<button type="button" id="btn-unsaved-cancel" class="btn">Abbrechen</button>
<button type="button" id="btn-unsaved-discard" class="btn">Nicht speichern</button>
<button type="button" id="btn-unsaved-save" class="btn">Speichern</button>
</div>
</div>
</dialog>
<dialog id="activateVersionDialog" class="rounded-2xl p-0 w-[440px]">
<div class="p-4 bg-white rounded-2xl space-y-4">
<h3 class="text-lg font-semibold">Neue Version aktivieren</h3>
<p class="text-sm text-slate-600">Soll die neu gespeicherte Version als aktiv gesetzt werden?</p>
<div class="flex justify-end gap-2">
<button type="button" id="btn-activate-cancel" class="btn">Abbrechen</button>
<button type="button" id="btn-activate-no" class="btn">Nein</button>
<button type="button" id="btn-activate-yes" class="btn">Ja</button>
</div>
</div>
</dialog>
<!-- Edit Snippet Dialog -->
<dialog id="editSnippetDialog" class="rounded-2xl p-0 w-[700px]">
<form id="editSnippetForm" method="dialog" class="p-4 bg-white rounded-2xl">
<h3 class="text-lg font-semibold mb-2">Snippet bearbeiten</h3>
<div class="space-y-3">
<label class="block">
<span class="text-sm text-slate-600">Name</span>
<input id="edit_snip_name" type="text" class="w-full border rounded-lg px-3 py-2" />
</label>
<label class="block">
<span class="text-sm text-slate-600">Content (HTML)</span>
<textarea id="edit_snip_content" class="w-full border rounded-lg px-3 py-2 h-64 font-mono text-sm"></textarea>
</label>
</div>
<div class="mt-4 flex justify-end gap-2">
<button type="button" id="editSnippetCancel" class="btn">Abbrechen</button>
<button type="submit" id="editSnippetSave" class="btn">Speichern</button>
</div>
</form>
</dialog>
<!-- Template Verwaltung Dialog -->
<dialog id="manageTemplateDialog" class="rounded-2xl p-0 w-[980px]">
<div class="p-4 bg-white rounded-2xl">
<div class="flex items-center gap-3">
<h3 class="text-lg font-semibold">Template Verwaltung</h3>
<span id="manage_tpl_badge" class="text-xs px-2 py-1 rounded-full bg-slate-100 text-slate-600">ID </span>
<div class="ms-auto flex gap-2">
<button type="button" id="manageTemplateClose" class="btn">Schließen</button>
</div>
</div>
<div class="mt-4">
<div class="space-y-3">
<label class="block">
<span class="text-sm text-slate-600">Name</span>
<input id="manage_tpl_name" type="text" class="w-full border rounded-lg px-3 py-2" />
</label>
<label id="manage_tpl_api_wrap" class="block">
<span class="text-sm text-slate-600">API Name (nur Templates)</span>
<input id="manage_tpl_api_name" type="text" class="w-full border rounded-lg px-3 py-2" />
<p id="manage_tpl_api_warn" class="text-xs text-amber-700 mt-1 hidden">Warnung: Das Ändern des API-Namens kann bestehende API-Integrationen brechen.</p>
</label>
<div class="mt-2">
<div class="text-sm font-semibold mb-2">Versionen</div>
<div id="manage_tpl_versions" class="space-y-2 text-sm text-slate-700"></div>
</div>
<div class="mt-3 flex items-center gap-2">
<button type="button" id="manageTemplateDelete" class="btn btn-danger">Template löschen</button>
<span id="manage_tpl_delete_hint" class="text-xs text-slate-500"></span>
</div>
</div>
</div>
</div>
</dialog>
<div id="toast-root"></div>
<?php
tpl_add_script(app_asset_url('/assets/js/toast.js'));
tpl_add_script(app_asset_url('/assets/js/app.js'), 'footer', false, false, '', null, true);
require __DIR__ . '/../partials/structure/layout_end.php';