Compare commits

...

2 commits

Author SHA1 Message Date
068f6c08f9 Merge pull request 'Entwicklerhinweis "Entwickelt von Loheide.eu"' (#3) from feature/credit into main
Some checks are pending
CI / PHP Lint (push) Waiting to run
CI / PHP Lint-1 (push) Waiting to run
CI / Unit Tests & Static Analysis (push) Waiting to run
2026-09-23 11:22:15 +00:00
7fa423a74c Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen
Some checks are pending
CI / PHP Lint (push) Waiting to run
CI / PHP Lint-1 (push) Waiting to run
CI / Unit Tests & Static Analysis (push) Waiting to run
CI / PHP Lint (pull_request) Waiting to run
CI / PHP Lint-1 (pull_request) Waiting to run
CI / Unit Tests & Static Analysis (pull_request) Waiting to run
Zentral in Ui::credit() gepflegt und dezent im Seitenfuß eingebunden:

- Admin-Bereich: unter dem Benutzerbereich in der Sidebar
- öffentliche Voucher-Seite: unter der Karte
- Anmeldung, Installer und Updater: am Ende der jeweiligen Karte
- Wartungsseite: direkt im Markup, da sie bewusst eigenständig bleibt
- README: im Kopf und in der Fußzeile

Der Hinweis ist übersetzt ("Entwickelt von" / "Developed by") und stört
das Branding der Betreiber nicht – die konfigurierbare Fußzeile der
Login-Seite bleibt unverändert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:21:53 +00:00
26 changed files with 45 additions and 2 deletions

View file

@ -4,6 +4,8 @@
**Webbasiertes WLAN-Voucher-Management für UniFi OS** mit Multi-Site-Support, Benutzerverwaltung, Microsoft-365-Login und integriertem Auto-Updater. **Webbasiertes WLAN-Voucher-Management für UniFi OS** mit Multi-Site-Support, Benutzerverwaltung, Microsoft-365-Login und integriertem Auto-Updater.
Entwickelt von **[Loheide.eu](https://loheide.eu)**
![PHP](https://img.shields.io/badge/PHP-7.4%2B-777BB4?logo=php&logoColor=white) ![PHP](https://img.shields.io/badge/PHP-7.4%2B-777BB4?logo=php&logoColor=white)
![MySQL](https://img.shields.io/badge/MySQL-5.7%2B%20%2F%20MariaDB-4479A1?logo=mysql&logoColor=white) ![MySQL](https://img.shields.io/badge/MySQL-5.7%2B%20%2F%20MariaDB-4479A1?logo=mysql&logoColor=white)
![UniFi OS](https://img.shields.io/badge/UniFi%20OS-7.0%2B-0559C9?logo=ubiquiti&logoColor=white) ![UniFi OS](https://img.shields.io/badge/UniFi%20OS-7.0%2B-0559C9?logo=ubiquiti&logoColor=white)
@ -541,4 +543,6 @@ vendor/bin/phpstan analyse
**Version 2.6.0** · Autor: **Friederich Loheide** · Lizenz: **MIT** **Version 2.6.0** · Autor: **Friederich Loheide** · Lizenz: **MIT**
Entwickelt von **[Loheide.eu](https://loheide.eu)**
</div> </div>

View file

@ -1535,6 +1535,20 @@ input.search-bar, .site-selector .search-bar { min-width: 240px; width: auto; fl
.print-qr { display: flex; justify-content: center; line-height: 0; } .print-qr { display: flex; justify-content: center; line-height: 0; }
.print-qr img, .print-qr canvas { display: block; } .print-qr img, .print-qr canvas { display: block; }
/* Entwicklerhinweis im Seitenfuß */
.app-credit {
margin: 0;
font-size: 11.5px;
color: var(--text-muted);
}
.app-credit a { color: var(--text-secondary); text-decoration: none; }
.app-credit a:hover { color: var(--accent); text-decoration: underline; }
.sidebar-foot .app-credit { margin-top: 10px; padding: 0 4px; text-align: center; }
.app-footer { max-width: 560px; margin: 20px auto 0; text-align: center; }
.login-container .app-credit { margin-top: 26px; text-align: center; }
.focus-card .app-credit { margin-top: 22px; text-align: center; }
.wrap .app-credit { margin-top: 18px; text-align: center; }
/* Sprungmarke zum Inhalt (nur bei Tastaturfokus sichtbar) */ /* Sprungmarke zum Inhalt (nur bei Tastaturfokus sichtbar) */
.skip-link { .skip-link {
position: absolute; position: absolute;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 390 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 KiB

After

Width:  |  Height:  |  Size: 384 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 KiB

After

Width:  |  Height:  |  Size: 320 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

After

Width:  |  Height:  |  Size: 316 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

After

Width:  |  Height:  |  Size: 313 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 KiB

After

Width:  |  Height:  |  Size: 472 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 MiB

After

Width:  |  Height:  |  Size: 1 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 250 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 309 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 KiB

After

Width:  |  Height:  |  Size: 330 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

After

Width:  |  Height:  |  Size: 278 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

After

Width:  |  Height:  |  Size: 285 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 235 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 235 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 KiB

After

Width:  |  Height:  |  Size: 416 KiB

Before After
Before After

View file

@ -116,6 +116,22 @@ class Ui
. '</style>'; . '</style>';
} }
/** Entwicklerhinweis bewusst an einer Stelle gepflegt. */
public const CREDIT_NAME = 'Loheide.eu';
public const CREDIT_URL = 'https://loheide.eu';
/**
* Dezenter Hinweis auf den Entwickler, wie er im Seitenfuß erscheint.
*/
public static function credit(): string
{
$label = function_exists('__') ? __('credit_by') : 'Entwickelt von';
return '<p class="app-credit">' . htmlspecialchars($label) . ' '
. '<a href="' . self::CREDIT_URL . '" target="_blank" rel="noopener">'
. self::CREDIT_NAME . '</a></p>';
}
/** /**
* Standard-Druckvorlage (wird nur verwendet, solange keine eigene * Standard-Druckvorlage (wird nur verwendet, solange keine eigene
* Vorlage gespeichert ist). {QR_CODE} fuellt der Browser. * Vorlage gespeichert ist). {QR_CODE} fuellt der Browser.

View file

@ -76,8 +76,8 @@ foreach ($navGroups as $items) {
<?php endforeach; ?> <?php endforeach; ?>
</nav> </nav>
<?php if ($currentUser): ?>
<div class="sidebar-foot"> <div class="sidebar-foot">
<?php if ($currentUser): ?>
<div class="user-menu" style="width:100%;justify-content:flex-start;"> <div class="user-menu" style="width:100%;justify-content:flex-start;">
<div class="user-avatar"><?= strtoupper(mb_substr($currentUser['name'], 0, 1)) ?></div> <div class="user-avatar"><?= strtoupper(mb_substr($currentUser['name'], 0, 1)) ?></div>
<div style="min-width:0;flex:1;"> <div style="min-width:0;flex:1;">
@ -88,8 +88,9 @@ foreach ($navGroups as $items) {
<i class="fas fa-arrow-right-from-bracket" aria-hidden="true"></i> <i class="fas fa-arrow-right-from-bracket" aria-hidden="true"></i>
</a> </a>
</div> </div>
</div>
<?php endif; ?> <?php endif; ?>
<?= Ui::credit() ?>
</div>
</aside> </aside>
<header class="topbar"> <header class="topbar">

View file

@ -635,6 +635,8 @@ function buildPrintCard($template, $data, $instructionHeader, $instructionText,
<?php endif; ?> <?php endif; ?>
</main> </main>
<footer class="app-footer no-print"><?= Ui::credit() ?></footer>
<div id="toast-container" role="status" aria-live="polite"></div> <div id="toast-container" role="status" aria-live="polite"></div>
<script src="assets/global.js"></script> <script src="assets/global.js"></script>
<script> <script>

View file

@ -375,6 +375,7 @@ if ($step === 5 && $_SERVER['REQUEST_METHOD'] === 'POST') {
<button type="submit" class="btn btn-primary btn-lg btn-block">Installation abschließen</button> <button type="submit" class="btn btn-primary btn-lg btn-block">Installation abschließen</button>
</form> </form>
<?php endif; ?> <?php endif; ?>
<?= Ui::credit() ?>
</div> </div>
</body> </body>
</html> </html>

View file

@ -469,6 +469,7 @@ return [
'settings_qr_hint' => '{QR_CODE} fügt einen QR-Code mit dem Voucher-Code ein.', 'settings_qr_hint' => '{QR_CODE} fügt einen QR-Code mit dem Voucher-Code ein.',
'print_valid_until' => 'Gültig bis', 'print_valid_until' => 'Gültig bis',
'print_devices' => 'Geräte', 'print_devices' => 'Geräte',
'credit_by' => 'Entwickelt von',
'settings_tab_general' => 'Allgemein', 'settings_tab_general' => 'Allgemein',
'settings_tab_defaults' => 'Voucher-Standards', 'settings_tab_defaults' => 'Voucher-Standards',
'settings_tab_cron' => 'Cron-Sync', 'settings_tab_cron' => 'Cron-Sync',

View file

@ -469,6 +469,7 @@ return [
'settings_qr_hint' => '{QR_CODE} inserts a QR code containing the voucher code.', 'settings_qr_hint' => '{QR_CODE} inserts a QR code containing the voucher code.',
'print_valid_until' => 'Valid until', 'print_valid_until' => 'Valid until',
'print_devices' => 'devices', 'print_devices' => 'devices',
'credit_by' => 'Developed by',
'settings_tab_general' => 'General', 'settings_tab_general' => 'General',
'settings_tab_defaults' => 'Voucher Defaults', 'settings_tab_defaults' => 'Voucher Defaults',
'settings_tab_cron' => 'Cron Sync', 'settings_tab_cron' => 'Cron Sync',

View file

@ -288,6 +288,7 @@ try {
<?php if ($publicAccess): ?> <?php if ($publicAccess): ?>
<div class="auth-links"><a href="index.php" class="back-link"><i class="fas fa-arrow-left" aria-hidden="true"></i> <?= __('login_back') ?></a></div> <div class="auth-links"><a href="index.php" class="back-link"><i class="fas fa-arrow-left" aria-hidden="true"></i> <?= __('login_back') ?></a></div>
<?php endif; ?> <?php endif; ?>
<?= Ui::credit() ?>
</div> </div>
</section> </section>

View file

@ -90,6 +90,7 @@
<p>Es wird gerade ein Update eingespielt. Die Seite ist in wenigen Augenblicken wieder erreichbar.</p> <p>Es wird gerade ein Update eingespielt. Die Seite ist in wenigen Augenblicken wieder erreichbar.</p>
<div class="bar"></div> <div class="bar"></div>
<p class="hint">Diese Seite aktualisiert sich automatisch.</p> <p class="hint">Diese Seite aktualisiert sich automatisch.</p>
<p class="hint" style="margin-top:10px;">Entwickelt von <a href="https://loheide.eu" style="color:inherit;">Loheide.eu</a></p>
</div> </div>
</body> </body>
</html> </html>

View file

@ -116,6 +116,7 @@ $channels = \Updater\UpdateManager::CHANNELS;
<div class="alert alert-ok" id="migAlert"></div> <div class="alert alert-ok" id="migAlert"></div>
</div> </div>
</div> </div>
<?= Ui::credit() ?>
</div> </div>
<script> <script>