release: v5.2.4 - Add footer to plugin and recompile styles

This commit is contained in:
Bartłomiej Janczak
2026-06-08 16:53:50 +02:00
parent db53540952
commit 77116ebae4
5 changed files with 262 additions and 2 deletions

View File

@@ -2877,4 +2877,92 @@ select.fi-select-input:disabled,
.create-link-sidebar-select-wrapper .fi-fo-field-wrp-label,
.create-link-sidebar-select-wrapper .fi-label {
font-weight: 600 !important;
}
.filamentshortUrl-panel-footer {
display: flex;
justify-content: center;
width: 100%;
margin-top: 1.75rem;
padding: 0 1rem 1rem;
}
.filamentshortUrl-panel-footer__card {
display: inline-flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 0.3125rem 0.4375rem;
max-width: 100%;
padding: 0.3125rem 0.625rem;
border-radius: 9999px;
background: rgb(244 244 245 / 0.85);
box-shadow: 0 0 0 1px rgb(0 0 0 / 0.04);
font-size: 0.6875rem;
line-height: 1.3;
color: rgb(113 113 122);
}
.dark .filamentshortUrl-panel-footer__card {
background: rgb(39 39 42 / 0.85);
box-shadow: 0 0 0 1px rgb(255 255 255 / 0.06);
color: rgb(161 161 170);
}
.filamentshortUrl-panel-footer__title {
font-weight: 600;
letter-spacing: -0.01em;
color: rgb(63 63 70);
}
.dark .filamentshortUrl-panel-footer__title {
color: rgb(228 228 231);
}
.filamentshortUrl-panel-footer__version {
padding: 0.0625rem 0.3125rem;
border-radius: 9999px;
background: rgb(254 243 199);
color: rgb(146 64 14);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 0.625rem;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.dark .filamentshortUrl-panel-footer__version {
background: rgb(69 26 3 / 0.55);
color: rgb(253 230 138);
}
.filamentshortUrl-panel-footer__meta {
color: inherit;
}
.filamentshortUrl-panel-footer__sep {
opacity: 0.35;
user-select: none;
}
.filamentshortUrl-panel-footer__link {
color: rgb(82 82 91);
text-decoration: none;
transition: color 0.15s ease;
}
.filamentshortUrl-panel-footer__link:hover {
color: rgb(180 83 9);
}
.dark .filamentshortUrl-panel-footer__link {
color: rgb(212 212 216);
}
.dark .filamentshortUrl-panel-footer__link:hover {
color: rgb(251 191 36);
}
.filamentshortUrl-panel-footer__package {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 0.625rem;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
@php
use Bjanczak\FilamentShortUrl\FilamentShortUrlPlugin;
$version = FilamentShortUrlPlugin::version();
@endphp
<footer class="filamentshortUrl-panel-footer" aria-label="Plugin footer">
<div class="filamentshortUrl-panel-footer__card">
<span class="filamentshortUrl-panel-footer__title">Filament Short URL</span>
<span class="filamentshortUrl-panel-footer__version">v{{ $version }}</span>
<span class="filamentshortUrl-panel-footer__sep" aria-hidden="true">·</span>
<span class="filamentshortUrl-panel-footer__meta">
{{ FilamentShortUrlPlugin::POWERED_BY_LABEL }}
<a
href="{{ FilamentShortUrlPlugin::AUTHOR_URL }}"
target="_blank"
rel="noopener noreferrer"
class="filamentshortUrl-panel-footer__link"
>
{{ FilamentShortUrlPlugin::AUTHOR_HANDLE }}
</a>
</span>
<span class="filamentshortUrl-panel-footer__sep" aria-hidden="true">·</span>
<a
href="{{ FilamentShortUrlPlugin::PACKAGE_URL }}"
target="_blank"
rel="noopener noreferrer"
class="filamentshortUrl-panel-footer__link filamentshortUrl-panel-footer__package"
>
{{ FilamentShortUrlPlugin::PACKAGE_NAME }}
</a>
</div>
</footer>

View File

@@ -16,9 +16,23 @@ use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Pages\ShortUrl
use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlTagResource;
use Filament\Contracts\Plugin;
use Filament\Panel;
use Filament\Support\Facades\FilamentView;
use Filament\View\PanelsRenderHook;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\View;
class FilamentShortUrlPlugin implements Plugin
{
public const PACKAGE_NAME = 'janczakb/filament-short-url';
public const PACKAGE_URL = 'https://github.com/janczakb/filament-short-url';
public const AUTHOR_HANDLE = 'bjanczak';
public const AUTHOR_URL = 'https://github.com/janczakb';
public const POWERED_BY_LABEL = 'Powered by';
protected ?string $navigationGroup = null;
protected ?int $navigationSort = null;
@@ -67,7 +81,88 @@ class FilamentShortUrlPlugin implements Plugin
public function boot(Panel $panel): void
{
// Configuration is consumed by ShortUrlResource via FilamentShortUrlPlugin::get()
FilamentView::registerRenderHook(
PanelsRenderHook::PAGE_END,
fn (): string => self::renderFooter(),
);
}
public static function renderFooter(): string
{
if (! self::shouldShowPluginFooter()) {
return '';
}
return View::make('filament-short-url::panel.footer')->render();
}
public static function version(): string
{
static $version = null;
if ($version !== null) {
return $version;
}
$composerPath = dirname(__DIR__).'/composer.json';
if (! is_readable($composerPath)) {
return $version = 'dev';
}
$decoded = json_decode((string) file_get_contents($composerPath), true);
return $version = is_array($decoded) && isset($decoded['version'])
? (string) $decoded['version']
: 'dev';
}
public static function shouldShowPluginFooter(?Request $request = null): bool
{
if (! config('filament-short-url.enabled', true)) {
return false;
}
$request ??= request();
if ($request === null) {
return false;
}
foreach (self::pluginPathPrefixes() as $prefix) {
if (self::pathMatchesPluginPrefix(trim($request->path(), '/'), $prefix)) {
return true;
}
}
$routeName = $request->route()?->getName();
if (! is_string($routeName)) {
return false;
}
return str_starts_with($routeName, 'filament.')
&& str_contains($routeName, 'short-url');
}
/**
* @return list<string>
*/
protected static function pluginPathPrefixes(): array
{
return [
'short-urls',
'short-url-pixels',
'short-url-custom-domains',
'short-url-folders',
'short-url-tags',
'short-url-settings',
];
}
protected static function pathMatchesPluginPrefix(string $path, string $prefix): bool
{
return (bool) preg_match('#(?:^|/)'.preg_quote($prefix, '#').'(?:/|$)#', $path);
}
// ─── Fluent configuration API ────────────────────────────────────────────

View File

@@ -0,0 +1,44 @@
<?php
use Bjanczak\FilamentShortUrl\FilamentShortUrlPlugin;
use Illuminate\Http\Request;
it('shows footer only on plugin routes', function () {
config(['filament-short-url.enabled' => true]);
expect(FilamentShortUrlPlugin::shouldShowPluginFooter(Request::create('/admin/short-urls')))
->toBeTrue()
->and(FilamentShortUrlPlugin::shouldShowPluginFooter(Request::create('/admin/short-url-settings')))
->toBeTrue()
->and(FilamentShortUrlPlugin::shouldShowPluginFooter(Request::create('/admin/short-url-pixels')))
->toBeTrue()
->and(FilamentShortUrlPlugin::shouldShowPluginFooter(Request::create('/admin/short-urls/create')))
->toBeTrue()
->and(FilamentShortUrlPlugin::shouldShowPluginFooter(Request::create('/admin/users')))
->toBeFalse();
});
it('hides footer when plugin is disabled', function () {
config(['filament-short-url.enabled' => false]);
expect(FilamentShortUrlPlugin::shouldShowPluginFooter(Request::create('/admin/short-urls')))
->toBeFalse();
});
it('renders footer view with package name and author handle', function () {
$this->app->instance('request', Request::create('/admin/short-urls'));
$html = FilamentShortUrlPlugin::renderFooter();
expect($html)
->toContain('Filament Short URL')
->toContain(FilamentShortUrlPlugin::POWERED_BY_LABEL)
->toContain(FilamentShortUrlPlugin::AUTHOR_HANDLE)
->toContain(FilamentShortUrlPlugin::PACKAGE_NAME);
});
it('returns empty footer html outside plugin routes', function () {
$this->app->instance('request', Request::create('/admin/users'));
expect(FilamentShortUrlPlugin::renderFooter())->toBe('');
});