Quelltext des aktuellen Standes
<?php $this->layout('layouts/admin', [
'page_title' => 'Netzwerkpläne – Diagram Editor',
'current_admin_page' => 'netdiagram-drawio',
]); ?>
<div class="settings-page">
<!-- Status Card -->
<section class="settings-card">
<div class="settings-card-header">
<span class="settings-card-icon">📷</span>
<div>
<h2><?= $this->te('Diagram Editor') ?></h2>
<p class="settings-card-desc">
<?= $this->t('Selbst-gehosteter Diagrammeditor. Wird direkt von GitHub Releases geladen und in <code>public/drawio/</code> installiert (nicht im Git-Repository).') ?>
</p>
</div>
</div>
<div class="settings-card-body">
<!-- Requirements check -->
<?php
$reqOk = !in_array(false, $requirements, true);
$reqLabels = [
'curl' => 'PHP cURL-Extension',
'zip' => 'PHP ZipArchive-Extension',
'writable' => 'Schreibrechte auf public/ und storage/',
];
?>
<?php if (!$reqOk): ?>
<div class="alert alert-danger" style="margin-bottom:1.25rem;">
<strong><?= $this->te('Voraussetzungen nicht erfüllt:') ?></strong>
<ul style="margin:0.5rem 0 0;padding-left:1.25rem;">
<?php foreach ($requirements as $key => $ok): ?>
<?php if (!$ok): ?>
<li><?= $reqLabels[$key] ?? $key ?></li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<!-- Install status -->
<div class="dw-status-row">
<div class="dw-status-icon <?= $is_installed ? 'dw-status-ok' : 'dw-status-missing' ?>">
<?= $is_installed ? '✓' : '◯' ?>
</div>
<div>
<div class="dw-status-label">
<?php if ($is_installed): ?>
<?= $this->te('Diagram Editor ist installiert') ?>
<?php if ($installed_version): ?>
<span class="badge badge-success"><?= $this->e($installed_version) ?></span>
<?php endif; ?>
<?php else: ?>
<?= $this->te('Diagram Editor ist') ?> <strong><?= $this->te('nicht installiert') ?></strong>
<?php endif; ?>
</div>
<div class="dw-status-sub">
<?php if ($is_installed): ?>
<?= $this->t('Installiert in <code>public/drawio/</code>') ?>
<?php else: ?>
<?= $this->te('Klicken Sie auf „Auf Updates prüfen“, um den Diagram Editor herunterzuladen und zu installieren.') ?>
<?php endif; ?>
</div>
</div>
</div>
<!-- GitHub release info (filled by JS) -->
<div id="dw-release-info" style="display:none;" class="dw-release-box">
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:0.5rem;">
<div>
<span class="dw-release-label"><?= $this->te('Neueste Version:') ?></span>
<strong id="dw-release-tag"></strong>
<span id="dw-release-date" style="font-size:0.8rem;color:var(--color-text-muted,var(--gray-500));margin-left:0.5rem;"></span>
</div>
<span id="dw-release-size" style="font-size:0.8rem;color:var(--color-text-muted,var(--gray-500));"></span>
</div>
<div id="dw-uptodate-msg" style="display:none;margin-top:0.5rem;color:var(--emerald-600);font-size:0.88rem;">
<?= $this->te('✓ draw.io ist aktuell.') ?>
</div>
</div>
<!-- Progress -->
<div id="dw-progress" style="display:none;margin-top:1rem;">
<div class="dw-progress-bar-wrap">
<div class="dw-progress-bar" id="dw-progress-bar"></div>
</div>
<div id="dw-progress-msg" style="font-size:0.82rem;color:var(--color-text-muted,var(--gray-500));margin-top:0.375rem;"></div>
</div>
<!-- Result -->
<div id="dw-result" style="display:none;margin-top:0.75rem;"></div>
<!-- Actions -->
<div style="display:flex;gap:0.625rem;margin-top:1.25rem;flex-wrap:wrap;">
<button id="dw-check-btn" class="btn btn-default" <?= !$reqOk ? 'disabled' : '' ?>>
<?= $this->te('🔍 Auf Updates prüfen') ?>
</button>
<button id="dw-install-btn" class="btn btn-primary" style="display:none;" <?= !$reqOk ? 'disabled' : '' ?>>
⬇ <?= $is_installed ? 'Diagram Editor aktualisieren' : 'Diagram Editor installieren' ?>
</button>
</div>
</div>
</section>
<!-- Info Card -->
<section class="settings-card">
<div class="settings-card-header">
<span class="settings-card-icon">ℹ</span>
<div>
<h2><?= $this->te('Informationen & Lizenz') ?></h2>
<p class="settings-card-desc"><?= $this->te('Technische Hinweise und Open-Source-Lizenz.') ?></p>
</div>
</div>
<div class="settings-card-body" style="font-size:0.88rem;line-height:1.6;color:var(--color-text-muted,var(--gray-700));">
<div style="background:var(--color-background,var(--gray-50));border:1px solid var(--color-border,var(--gray-200));border-radius:0.375rem;padding:0.875rem 1rem;margin-bottom:1.25rem;font-size:0.82rem;">
<?= $this->t('Dieser Diagram Editor basiert auf <a href="https://www.diagrams.net/" target="_blank" rel="noopener"><strong>diagrams.net</strong></a> (ehemals draw.io), lizenziert unter der <a href="https://www.apache.org/licenses/LICENSE-2.0" target="_blank" rel="noopener">Apache License 2.0</a>. „draw.io“ ist eine eingetragene Marke von JGraph Ltd.') ?>
</div>
<ul style="padding-left:1.25rem;margin:0;display:flex;flex-direction:column;gap:0.375rem;">
<li><?= $this->t('Der Editor läuft als <strong>statische Web-App</strong> in <code>public/drawio/</code> – kein Java, kein Docker erforderlich.') ?></li>
<li><?= $this->t('Die Dateien werden <strong>direkt von GitHub Releases</strong> (<a href="https://github.com/jgraph/drawio" target="_blank" rel="noopener">jgraph/drawio</a>) heruntergeladen (~50 MB).') ?></li>
<li><?= $this->t('Das Verzeichnis <code>public/drawio/</code> ist in <code>.gitignore</code> – es wird <strong>nicht ins Repository committet</strong>.') ?></li>
<li><?= $this->t('Netzwerkpläne werden als <strong>Diagramm-XML</strong> in der Datenbank gespeichert.') ?></li>
<li><?= $this->t('Bestehende <code>.drawio</code>-Dateien können über „Netzwerkpläne“ hochgeladen werden.') ?></li>
</ul>
</div>
</section>
</div>
<script>
(function () {
var CSRF = <?= json_encode($this->csrf()) ?>;
var IS_INSTALLED = <?= $is_installed ? 'true' : 'false' ?>;
var checkBtn = document.getElementById('dw-check-btn');
var installBtn = document.getElementById('dw-install-btn');
var releaseInfo = document.getElementById('dw-release-info');
var releaseTag = document.getElementById('dw-release-tag');
var releaseDate = document.getElementById('dw-release-date');
var releaseSize = document.getElementById('dw-release-size');
var upToDate = document.getElementById('dw-uptodate-msg');
var progress = document.getElementById('dw-progress');
var progressBar = document.getElementById('dw-progress-bar');
var progressMsg = document.getElementById('dw-progress-msg');
var resultDiv = document.getElementById('dw-result');
var pendingDownloadUrl = '';
var pendingVersion = '';
// ----------------------------------------------------------------
// Check for updates
// ----------------------------------------------------------------
checkBtn.addEventListener('click', function () {
checkBtn.disabled = true;
checkBtn.textContent = 'Prüfe...';
resultDiv.style.display = 'none';
fetch('/admin/netdiagram/drawio/check', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: '_csrf=' + encodeURIComponent(CSRF)
})
.then(function (r) { return r.json(); })
.then(function (d) {
checkBtn.disabled = false;
checkBtn.innerHTML = '🔍 Auf Updates prüfen';
if (!d.ok) {
showResult('error', 'Fehler: ' + d.error);
return;
}
// Show release info
releaseTag.textContent = d.tag;
releaseSize.textContent = d.size_mb + ' MB';
if (d.published_at) {
var dt = new Date(d.published_at);
releaseDate.textContent = '(' + dt.toLocaleDateString('de-DE') + ')';
}
releaseInfo.style.display = 'block';
if (d.up_to_date) {
upToDate.style.display = 'block';
installBtn.style.display = 'none';
} else {
upToDate.style.display = 'none';
pendingDownloadUrl = d.download_url;
pendingVersion = d.tag;
installBtn.style.display = '';
installBtn.innerHTML = IS_INSTALLED
? '⬇ Auf ' + d.tag + ' aktualisieren'
: '⬇ Diagram Editor ' + d.tag + ' installieren';
}
})
.catch(function (e) {
checkBtn.disabled = false;
checkBtn.innerHTML = '🔍 Auf Updates prüfen';
showResult('error', 'Netzwerkfehler: ' + e.message);
});
});
// ----------------------------------------------------------------
// Install / Update
// ----------------------------------------------------------------
installBtn.addEventListener('click', function () {
if (!pendingDownloadUrl) return;
installBtn.disabled = true;
checkBtn.disabled = true;
resultDiv.style.display = 'none';
progress.style.display = 'block';
progressBar.style.width = '10%';
progressMsg.textContent = 'Verbindung wird hergestellt...';
// Animate progress bar while waiting
var pct = 10;
var timer = setInterval(function () {
if (pct < 85) { pct += 2; progressBar.style.width = pct + '%'; }
}, 800);
fetch('/admin/netdiagram/drawio/install', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: '_csrf=' + encodeURIComponent(CSRF)
+ '&download_url=' + encodeURIComponent(pendingDownloadUrl)
+ '&version=' + encodeURIComponent(pendingVersion)
})
.then(function (r) { return r.json(); })
.then(function (d) {
clearInterval(timer);
progressBar.style.width = '100%';
if (d.ok) {
progressMsg.textContent = 'Fertig!';
setTimeout(function () { progress.style.display = 'none'; }, 800);
showResult('success', 'Diagram Editor ' + d.version + ' wurde erfolgreich installiert.');
installBtn.style.display = 'none';
IS_INSTALLED = true;
// Reload to refresh status
setTimeout(function () { location.reload(); }, 1500);
} else {
progressBar.style.width = '0';
progress.style.display = 'none';
showResult('error', 'Installation fehlgeschlagen: ' + d.error);
installBtn.disabled = false;
checkBtn.disabled = false;
}
})
.catch(function (e) {
clearInterval(timer);
progress.style.display = 'none';
showResult('error', 'Netzwerkfehler: ' + e.message);
installBtn.disabled = false;
checkBtn.disabled = false;
});
});
function showResult(type, msg) {
resultDiv.style.display = 'block';
resultDiv.className = type === 'success' ? 'alert alert-success' : 'alert alert-danger';
resultDiv.textContent = msg;
}
}());
</script>
<style>
.dw-status-row { display: flex; align-items: flex-start; gap: 0.875rem; padding: 0.875rem 0; }
.dw-status-icon { width: 2rem; height: 2rem; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 1rem; flex-shrink: 0; }
.dw-status-ok { background: var(--emerald-100); color: var(--emerald-600); }
.dw-status-missing { background: var(--gray-100); color: var(--gray-400); }
.dw-status-label { font-weight: 500; font-size: 0.9rem; }
.dw-status-sub { font-size: 0.8rem; color: var(--color-text-muted, var(--gray-500)); margin-top: 0.125rem; }
.badge { display: inline-block; padding: 0.125rem 0.5rem; border-radius: 0.25rem; font-size: 0.75rem; font-weight: 600; }
.badge-success { background: var(--emerald-100); color: var(--emerald-600); }
.dw-release-box { background: var(--color-background, var(--gray-50)); border: 1px solid var(--color-border, var(--gray-200)); border-radius: 0.375rem; padding: 0.875rem 1rem; margin-top: 0.875rem; }
.dw-release-label { font-size: 0.82rem; color: var(--color-text-muted, var(--gray-500)); margin-right: 0.25rem; }
.dw-progress-bar-wrap { height: 6px; background: var(--color-border, var(--gray-200)); border-radius: 3px; overflow: hidden; }
.dw-progress-bar { height: 100%; background: var(--blue-500); border-radius: 3px; width: 0; transition: width 0.4s ease; }
/* Reuse settings-card styles */
</style>