release: v5.2.4 - Add footer to plugin and recompile styles
This commit is contained in:
@@ -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-fo-field-wrp-label,
|
||||||
.create-link-sidebar-select-wrapper .fi-label {
|
.create-link-sidebar-select-wrapper .fi-label {
|
||||||
font-weight: 600 !important;
|
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;
|
||||||
}
|
}
|
||||||
2
resources/dist/filament-short-url.css
vendored
2
resources/dist/filament-short-url.css
vendored
File diff suppressed because one or more lines are too long
33
resources/views/panel/footer.blade.php
Normal file
33
resources/views/panel/footer.blade.php
Normal 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>
|
||||||
@@ -16,9 +16,23 @@ use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Pages\ShortUrl
|
|||||||
use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlTagResource;
|
use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlTagResource;
|
||||||
use Filament\Contracts\Plugin;
|
use Filament\Contracts\Plugin;
|
||||||
use Filament\Panel;
|
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
|
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 ?string $navigationGroup = null;
|
||||||
|
|
||||||
protected ?int $navigationSort = null;
|
protected ?int $navigationSort = null;
|
||||||
@@ -67,7 +81,88 @@ class FilamentShortUrlPlugin implements Plugin
|
|||||||
|
|
||||||
public function boot(Panel $panel): void
|
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 ────────────────────────────────────────────
|
// ─── Fluent configuration API ────────────────────────────────────────────
|
||||||
|
|||||||
44
tests/Unit/PluginFooterTest.php
Normal file
44
tests/Unit/PluginFooterTest.php
Normal 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('');
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user