OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

drawio.php

14 KB
<?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">&#128247;</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 ? '&#10003;' : '&#9711;' ?>
                </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 &bdquo;Auf Updates pr&uuml;fen&ldquo;, 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('&#10003; 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('&#128269; Auf Updates pr&uuml;fen') ?>
                </button>
                <button id="dw-install-btn" class="btn btn-primary" style="display:none;" <?= !$reqOk ? 'disabled' : '' ?>>
                    &#11015; <?= $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">&#8505;</span>
            <div>
                <h2><?= $this->te('Informationen &amp; 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>. &bdquo;draw.io&ldquo; 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&auml;uft als <strong>statische Web-App</strong> in <code>public/drawio/</code> &ndash; 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&nbsp;MB).') ?></li>
                <li><?= $this->t('Das Verzeichnis <code>public/drawio/</code> ist in <code>.gitignore</code> &ndash; es wird <strong>nicht ins Repository committet</strong>.') ?></li>
                <li><?= $this->t('Netzwerkpl&auml;ne werden als <strong>Diagramm-XML</strong> in der Datenbank gespeichert.') ?></li>
                <li><?= $this->t('Bestehende <code>.drawio</code>-Dateien k&ouml;nnen &uuml;ber &bdquo;Netzwerkpl&auml;ne&ldquo; 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 = '&#128269; Auf Updates pr&uuml;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
                    ? '&#11015; Auf ' + d.tag + ' aktualisieren'
                    : '&#11015; Diagram Editor ' + d.tag + ' installieren';
            }
        })
        .catch(function (e) {
            checkBtn.disabled = false;
            checkBtn.innerHTML = '&#128269; Auf Updates pr&uuml;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>