Files
filament-short-url/resources/views/stats.blade.php
Bartłomiej Janczak eda4794cac feat: v1.2.0 — password protection, warning pages, smart targeting, rate limiting, daily stats aggregation
- Add password-protected links with session-based unlock flow
- Add redirect warning (interstitial) pages before external URLs
- Add smart targeting rules: device-based, country/geo, A/B weighted rotation
- Add configurable per-IP rate limiting with 429 + Retry-After headers
- Add daily stats aggregation & log pruning (short-url:aggregate-and-prune)
- Add IncrementVisitJob as queue-based counter buffering fallback
- Add ShortUrlDailyStats model with JSON stat columns per day
- Add two new migrations: targeting/security fields, daily_stats table
- Add password-prompt.blade.php and warning.blade.php views
- Extend Settings GUI with Performance & Security tab (aggregation + rate limiting)
- Extend ShortUrlForm with Targeting & Security section
- Add POST route for password form submission (was GET-only → 405)
- Replace enum(device_type) with string(20) for cross-DB compatibility
- Remove ->after() MySQL-only hints from ALTER TABLE migrations
- Fix aggregation test: use whereDate() instead of assertDatabaseHas for date column
- Extend en/pl translations for all new features
- Expand README.md with full v1.2.0 documentation (476 lines)
2026-06-01 13:54:13 +02:00

64 lines
2.5 KiB
PHP

<x-filament-panels::page>
<x-filament::tabs class="mb-6">
<x-filament::tabs.item
:active="true"
icon="heroicon-m-presentation-chart-line"
>
{{ __('filament-short-url::default.stats_tab_statistics') }}
</x-filament::tabs.item>
<x-filament::tabs.item
tag="a"
href="{{ \Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource::getUrl('stats.logs', ['record' => $record]) }}"
icon="heroicon-m-list-bullet"
>
{{ __('filament-short-url::default.stats_tab_visit_logs') }}
</x-filament::tabs.item>
</x-filament::tabs>
@php
$dateFrom = $this->filterData['date_from'] ?? null;
$dateTo = $this->filterData['date_to'] ?? null;
$isCustom = ($this->filterData['preset'] ?? '') === 'custom';
@endphp
<div class="space-y-6">
<div class="flex justify-end items-center">
<div class="w-full {{ $isCustom ? 'max-w-xl' : 'max-w-[200px]' }}">
<form>
{{ $this->form }}
</form>
</div>
</div>
@livewire(\Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Widgets\ShortUrlStatsOverview::class, [
'record' => $record,
'dateFrom' => $dateFrom,
'dateTo' => $dateTo,
], key('stats-overview-' . $dateFrom . '-' . $dateTo))
<div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
<div class="lg:col-span-2">
@livewire(\Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Widgets\ShortUrlVisitsChart::class, [
'record' => $record,
'dateFrom' => $dateFrom,
'dateTo' => $dateTo,
], key('stats-chart-' . $dateFrom . '-' . $dateTo))
</div>
<div>
@livewire(\Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Widgets\ShortUrlVisitsRightBreakdown::class, [
'record' => $record,
'dateFrom' => $dateFrom,
'dateTo' => $dateTo,
], key('stats-right-breakdown-' . $dateFrom . '-' . $dateTo))
</div>
</div>
@livewire(\Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Widgets\ShortUrlVisitsBottomBreakdown::class, [
'record' => $record,
'dateFrom' => $dateFrom,
'dateTo' => $dateTo,
], key('stats-bottom-breakdown-' . $dateFrom . '-' . $dateTo))
</div>
</x-filament-panels::page>