OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

relution_list.php

9 KB
<?php $this->layout('layouts/admin', [
    'page_title'         => 'Relution MDM',
    'current_admin_page' => 'relution-mdm',
]); ?>
<?php $connections = $connections ?? []; ?>

<div class="settings-page">
    <section class="settings-card">
        <div class="settings-card-header">
            <span class="settings-card-icon">&#128241;</span>
            <div>
                <h2><?= $this->te('Relution-Instanzen') ?></h2>
                <p class="settings-card-desc">
                    <?= $this->te('Woher die verwalteten Geräte stammen. Mehrere Instanzen nebeneinander sind möglich &ndash; je Kunde oder Mandant eine, jede mit eigenen Zugangsdaten und Filtern.') ?>
                </p>
            </div>
        </div>
        <div class="settings-card-body" style="padding:0;">
            <?php if (empty($connections)): ?>
            <div class="empty-state" style="padding:2rem;">
                <i class="fas fa-mobile-alt" aria-hidden="true"></i>
                <p><?= $this->te('Noch keine Instanz eingerichtet.') ?></p>
            </div>
            <?php else: ?>
            <div class="table-wrapper">
                <table class="data-table">
                    <thead>
                        <tr>
                            <th scope="col"><?= $this->te('Name') ?></th>
                            <th scope="col"><?= $this->t('Server') ?></th>
                            <th scope="col"><?= $this->te('Geräte') ?></th>
                            <th scope="col"><?= $this->te('Letzter Abgleich') ?></th>
                            <th scope="col"><?= $this->te('Zustand') ?></th>
                            <th scope="col"></th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php foreach ($connections as $c): ?>
                        <?php $s = (array)($c['settings'] ?? []); ?>
                        <tr>
                            <td>
                                <strong><?= $this->e($c['name']) ?></strong>
                                <?php if (empty($c['enabled'])): ?>
                                <span class="status-pill status-pill--neutral"><?= $this->te('aus') ?></span>
                                <?php endif; ?>
                                <?php if (empty($s['server_url']) || empty($s['access_token'])): ?>
                                <br><small class="text-danger"><?= $this->te('Zugangsdaten unvollständig &ndash; bitte bearbeiten') ?></small>
                                <?php endif; ?>
                            </td>
                            <td><small><?= $this->e((string)($s['server_url'] ?? '–')) ?></small></td>
                            <td><?= (int)$c['device_count'] ?></td>
                            <td>
                                <?php if (!empty($c['last_run_at'])): ?>
                                    <?= date('d.m.Y H:i', strtotime((string)$c['last_run_at'])) ?>
                                <?php else: ?>
                                    <small class="text-muted"><?= $this->te('noch nie') ?></small>
                                <?php endif; ?>
                            </td>
                            <td>
                                <?php if ($c['last_status'] === 'ok'): ?>
                                    <span class="status-pill status-pill--success"><?= $this->e((string)$c['last_message']) ?></span>
                                <?php elseif ($c['last_status'] === 'error'): ?>
                                    <span class="status-pill status-pill--danger"><?= $this->te('Fehler') ?></span><br>
                                    <small class="text-muted"><?= $this->e((string)$c['last_message']) ?></small>
                                <?php else: ?>
                                    <small class="text-muted">–</small>
                                <?php endif; ?>
                            </td>
                            <td style="white-space:nowrap;text-align:right;">
                                <button type="button" class="btn btn-default btn-sm" onclick="relSync(<?= (int)$c['id'] ?>, true)"><?= $this->te('Probelauf') ?></button>
                                <button type="button" class="btn btn-default btn-sm" onclick="relSync(<?= (int)$c['id'] ?>, false)"><?= $this->te('Abgleichen') ?></button>
                                <a href="/admin/inventory/relution/<?= (int)$c['id'] ?>/edit" class="btn btn-default btn-sm"><?= $this->te('Bearbeiten') ?></a>
                                <form method="POST" action="/admin/inventory/relution/<?= (int)$c['id'] ?>/delete" style="display:inline;"
                                      onsubmit="return confirm('Instanz „<?= $this->e(addslashes($c['name'])) ?>“ entfernen? Die Geräte bleiben erhalten und sind danach wieder von Hand pflegbar.');">
                                    <input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
                                    <button type="submit" class="btn btn-danger btn-sm"><?= $this->te('Entfernen') ?></button>
                                </form>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <?php endif; ?>
        </div>
        <div class="settings-card-body" style="display:flex;gap:.75rem;flex-wrap:wrap;align-items:center;">
            <a href="/admin/inventory/relution/new" class="btn btn-primary"><?= $this->te('Instanz hinzufügen') ?></a>
            <button type="button" class="btn btn-default" onclick="relSync(null, false)"><?= $this->te('Alle abgleichen') ?></button>
            <?php if (!empty($last_sync)): ?>
            <small class="text-muted"><?= $this->t('Zuletzt') ?>: <?= date('d.m.Y H:i', strtotime((string)$last_sync)) ?></small>
            <?php endif; ?>
        </div>
        <div class="settings-card-body" id="rel-ergebnis" style="display:none;"></div>
    </section>

    <section class="settings-card">
        <div class="settings-card-header">
            <span class="settings-card-icon">&#128336;</span>
            <div>
                <h2><?= $this->te('Zeitplan') ?></h2>
                <p class="settings-card-desc"><?= $this->te('Der regelmäßige Abgleich läuft über den gemeinsamen Zeitplan.') ?></p>
            </div>
        </div>
        <div class="settings-card-body">
            <p style="line-height:1.55;">
                <?= $this->t('Die Aufgabe <code>relution_sync</code> gleicht alle <strong>eingeschalteten</strong> Instanzen nacheinander ab. Eine Instanz, die gerade nicht erreichbar ist, hält die übrigen nicht auf. Intervall und Ein-/Ausschalten unter <a href="/admin/cronjobs">Cronjobs</a>.') ?>
            </p>
            <p style="line-height:1.55;">
                <?= $this->t('Geräte, die eine Instanz beim Abgleich nicht mehr meldet, werden ausgemustert &ndash; aber nur innerhalb <em>ihrer</em> Instanz. Die Geräte der übrigen bleiben unberührt, und auch die Sicherheitsgrenze für den Höchstanteil misst je Instanz.') ?>
            </p>
        </div>
    </section>
</div>

<script>
/**
 * Stösst einen Abgleich an. Ohne ID laufen alle eingeschalteten Instanzen.
 */
function relSync(id, dryRun) {
    var ziel = id === null
        ? '/admin/inventory/relution/sync'
        : '/admin/inventory/relution/' + id + (dryRun ? '/preview' : '/sync');

    var kasten = document.getElementById('rel-ergebnis');
    kasten.style.display = '';
    kasten.innerHTML = '<em>Läuft…</em>';

    fetch(ziel, {
        method: 'POST',
        headers: {
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content,
            'X-Requested-With': 'XMLHttpRequest'
        }
    })
    .then(function (r) { return r.json(); })
    .then(function (d) {
        var teile = [];
        teile.push('<strong>' + (d.dry_run ? 'Probelauf' : 'Abgleich') + ': '
                 + (d.ok ? 'abgeschlossen' : 'mit Fehlern') + '</strong>');
        if (d.instances) {
            d.instances.forEach(function (i) {
                teile.push('<div>' + esc(i.name) + ': ' + esc(i.message) + '</div>');
            });
        } else if (d.message) {
            teile.push('<div>' + esc(d.message) + '</div>');
        }
        kasten.innerHTML = teile.join('');
        if (!d.dry_run && d.ok) { setTimeout(function () { location.reload(); }, 1500); }
    })
    .catch(function () { kasten.innerHTML = '<span class="text-danger">Netzwerkfehler.</span>'; });
}

function esc(s) {
    var d = document.createElement('div');
    d.textContent = s === undefined || s === null ? '' : String(s);
    return d.innerHTML;
}
</script>