feat: Loosen-IT logo top right on the settings page

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-26 15:26:44 +02:00
co-authored by Claude Opus 5.5
parent 909ac82594
commit 68ca4f45ec
4 changed files with 42 additions and 4 deletions
+1
View File
@@ -0,0 +1 @@
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 499.41 107.88"><defs><style>.cls-1{fill:#2a4b9a;}</style></defs><path class="cls-1" d="M102.16,28.36A25.62,25.62,0,0,0,76.57,52.87H93.84A8.4,8.4,0,1,1,94,55.93H76.63a25.61,25.61,0,1,0,25.53-27.57Z"/><path class="cls-1" d="M76.51,55.93a22,22,0,1,1,.06-3.06H80.2a25.68,25.68,0,1,0-.06,3.06Z"/><path class="cls-1" d="M76.57,52.87H63a8.4,8.4,0,1,0-.15,3.06H76.5c.06-.64.09-1.3.09-2C76.59,53.6,76.58,53.23,76.57,52.87Z"/><path d="M166.64,72.58H153.42V29h-8V78.87h25.29V76.93A30.68,30.68,0,0,1,166.64,72.58Z"/><path d="M313,35.49V50.61h18.37v6.22H313V72.3h20.48v6.56H304.91V29h28.53v6.49Z"/><path d="M381.62,78.86h-8.05l-24.23-36.8v36.8h-8.06V29.07h8.06L373.57,66V29.07h8.05Z"/><path d="M415.8,53v6.76h-29V53Z"/><path d="M428.58,29V78.88h-8.05V29Z"/><path d="M470.4,29v6.5H456.48V78.88h-8.12V35.51H434.51V29Z"/><path d="M294.77,58a14.11,14.11,0,0,0-5.08-4.42,52.49,52.49,0,0,0-7.74-3q-3.74-1.27-5.9-2.23a9.72,9.72,0,0,1-3.56-2.61,6.2,6.2,0,0,1-1.41-4.2,6.16,6.16,0,0,1,2-5,8.18,8.18,0,0,1,5.44-1.73,8.31,8.31,0,0,1,5.9,2,8.46,8.46,0,0,1,2.65,4.84h8.69A13.87,13.87,0,0,0,290.68,32c-3-2.45-7-3.67-12.12-3.67A20.29,20.29,0,0,0,270.09,30a12.79,12.79,0,0,0-5.65,4.7A11.66,11.66,0,0,0,263,38a30.5,30.5,0,0,1,4.44,14.2,14.28,14.28,0,0,0,2.09,1.34,53.22,53.22,0,0,0,7.59,3q3.81,1.28,6,2.26a10.49,10.49,0,0,1,3.68,2.72,6.61,6.61,0,0,1,1.48,4.42,6.82,6.82,0,0,1-2,5.08,7.79,7.79,0,0,1-5.69,2A9.06,9.06,0,0,1,274,70.6,8.77,8.77,0,0,1,271.22,65h-5.8a30.9,30.9,0,0,1-1.92,4.07,14.16,14.16,0,0,0,1.85,3.42,15.93,15.93,0,0,0,6.43,5,22.08,22.08,0,0,0,9.11,1.8,18.68,18.68,0,0,0,8.83-1.91,12.83,12.83,0,0,0,5.37-5,13.65,13.65,0,0,0,1.77-6.81A12.77,12.77,0,0,0,294.77,58Z"/><path class="cls-1" d="M236.7,28.4a25.58,25.58,0,0,0-22.78,14,25.59,25.59,0,1,0,0,23.28A25.59,25.59,0,1,0,236.7,28.4ZM191.13,74a20,20,0,1,1,20-21c0,.34,0,.67,0,1s0,.67,0,1A20.06,20.06,0,0,1,191.13,74Zm45.57,0a20.06,20.06,0,0,1-20-19c0-.33,0-.67,0-1s0-.67,0-1A20,20,0,1,1,236.7,74Z"/></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+23 -3
View File
@@ -14,8 +14,11 @@ final class SettingsPage
/** @var array<string, AdminTab> */ /** @var array<string, AdminTab> */
private array $tabs = []; private array $tabs = [];
/** @param list<AdminTab> $tabs The first tab is the default. */ /**
public function __construct(array $tabs) * @param list<AdminTab> $tabs The first tab is the default.
* @param string $logoUrl Loosen-IT logo shown top right of the page ('' = none).
*/
public function __construct(array $tabs, private string $logoUrl = '')
{ {
foreach ($tabs as $tab) { foreach ($tabs as $tab) {
$this->tabs[$tab->slug()] = $tab; $this->tabs[$tab->slug()] = $tab;
@@ -78,7 +81,9 @@ final class SettingsPage
} }
$current = $this->currentTab(); $current = $this->currentTab();
echo '<div class="wrap"><h1>' . esc_html__('LIT MCP', 'wp-lit-mcp') . '</h1>'; echo '<div class="wrap">';
$this->renderLogo();
echo '<h1>' . esc_html__('LIT MCP', 'wp-lit-mcp') . '</h1>';
$this->renderNotice(); $this->renderNotice();
echo '<nav class="nav-tab-wrapper">'; echo '<nav class="nav-tab-wrapper">';
foreach ($this->tabs as $slug => $tab) { foreach ($this->tabs as $slug => $tab) {
@@ -94,6 +99,21 @@ final class SettingsPage
echo '</div>'; echo '</div>';
} }
private function renderLogo(): void
{
if ($this->logoUrl === '') {
return;
}
printf(
'<div class="lit-mcp-header"><a href="https://loosen-it.de" target="_blank" rel="noopener">'
. '<img src="%s" alt="Loosen-IT Logo" class="lit-mcp-logo"></a></div>'
. '<style>.lit-mcp-header{position:relative}.lit-mcp-logo{position:absolute;padding:10px;right:0;'
. 'top:0;height:30px;width:auto}@media (max-width:782px){.lit-mcp-logo{height:24px}}</style>',
esc_url($this->logoUrl)
);
}
private function renderNotice(): void private function renderNotice(): void
{ {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display only. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display only.
+1 -1
View File
@@ -90,7 +90,7 @@ final class Plugin
new ToolsTab($registry, $policy), new ToolsTab($registry, $policy),
new LogTab($changeLog, $limits), new LogTab($changeLog, $limits),
new LimitsTab(), new LimitsTab(),
]); ], plugins_url('assets/img/loosen-it-logo.svg', self::$pluginFile));
if (is_admin()) { if (is_admin()) {
self::$settingsPage->register(); self::$settingsPage->register();
(new AdminNotices($status))->register(); (new AdminNotices($status))->register();
+17
View File
@@ -57,6 +57,23 @@ final class SettingsPageTest extends TestCase
self::assertSame(['verbindung', 'zugriff'], $page->tabSlugs()); self::assertSame(['verbindung', 'zugriff'], $page->tabSlugs());
} }
public function testRendersTheLogoTopRightOnlyWhenGiven(): void
{
Functions\when('current_user_can')->justReturn(true);
Functions\when('esc_url')->returnArg();
ob_start();
(new SettingsPage([$this->tab('verbindung', 'Verbindung')], 'https://example.test/logo.svg'))->render();
$withLogo = (string) ob_get_clean();
ob_start();
(new SettingsPage([$this->tab('verbindung', 'Verbindung')]))->render();
$withoutLogo = (string) ob_get_clean();
self::assertStringContainsString('<img src="https://example.test/logo.svg" alt="Loosen-IT Logo"', $withLogo);
self::assertStringContainsString('right:0', $withLogo);
self::assertStringNotContainsString('lit-mcp-logo', $withoutLogo);
}
public function testUnknownTabFallsBackToTheFirstAndNoticesAreShown(): void public function testUnknownTabFallsBackToTheFirstAndNoticesAreShown(): void
{ {
Functions\when('current_user_can')->justReturn(true); Functions\when('current_user_can')->justReturn(true);