- 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)
64 lines
2.5 KiB
PHP
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>
|