feat: initial project setup with Laravel 12 and Filament v4
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Models\SyncLog;
|
||||
use App\Services\SyncService;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\Page;
|
||||
use Morilog\Jalali\Jalalian;
|
||||
|
||||
class SyncPage extends Page
|
||||
{
|
||||
protected string $view = 'filament.pages.sync-page';
|
||||
|
||||
protected static ?int $navigationSort = 99;
|
||||
|
||||
public static function canAccess(): bool
|
||||
{
|
||||
return auth()->user()->can('View:SyncPage');
|
||||
}
|
||||
|
||||
public static function shouldRegisterNavigation(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getNavigationIcon(): \BackedEnum|string|null
|
||||
{
|
||||
return 'heroicon-o-arrows-right-left';
|
||||
}
|
||||
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('navigation.groups.system');
|
||||
}
|
||||
|
||||
public string $report = '';
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('navigation.sync.label');
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return __('navigation.sync.title');
|
||||
}
|
||||
|
||||
public function getPendingCount(): int
|
||||
{
|
||||
return SyncLog::changesSince(SyncLog::lastSyncId())->count();
|
||||
}
|
||||
|
||||
public function getLastSyncTime(): string
|
||||
{
|
||||
$last = SyncLog::where('action', 'synced')->latest('id')->first();
|
||||
if (! $last) {
|
||||
return __('navigation.sync.never');
|
||||
}
|
||||
|
||||
return Jalalian::fromCarbon($last->datetime->timezone('Asia/Tehran'))->format('Y/m/d H:i:s');
|
||||
}
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Action::make('sync')
|
||||
->label(__('navigation.sync.sync_with_peer'))
|
||||
->icon('heroicon-o-arrows-right-left')
|
||||
->color('primary')
|
||||
->requiresConfirmation()
|
||||
->modalHeading(__('navigation.sync.confirm_heading'))
|
||||
->modalDescription(__('navigation.sync.confirm_description'))
|
||||
->modalSubmitActionLabel(__('navigation.sync.confirm_button'))
|
||||
->action('runSync'),
|
||||
|
||||
Action::make('backup')
|
||||
->label(__('navigation.backup.label'))
|
||||
->icon('heroicon-o-arrow-down-tray')
|
||||
->color('success')
|
||||
->action('downloadBackup'),
|
||||
];
|
||||
}
|
||||
|
||||
public function runSync(): void
|
||||
{
|
||||
$service = SyncService::fromConfig();
|
||||
|
||||
if (! $service->isConfigured()) {
|
||||
Notification::make()
|
||||
->title(__('navigation.sync.error_title'))
|
||||
->body(__('navigation.sync.error_not_configured'))
|
||||
->danger()
|
||||
->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $service->sync();
|
||||
|
||||
$this->report = implode("\n", $result['report']);
|
||||
|
||||
Notification::make()
|
||||
->title($result['success'] ? __('navigation.sync.success') : __('navigation.sync.failed'))
|
||||
->body(__('navigation.sync.see_report'))
|
||||
->color($result['success'] ? 'success' : 'warning')
|
||||
->send();
|
||||
}
|
||||
|
||||
public function downloadBackup(): \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
{
|
||||
$data = [
|
||||
'exported_at' => now()->toDateTimeString(),
|
||||
'last_sync_id' => SyncLog::lastSyncId(),
|
||||
'changes' => SyncLog::all()->toArray(),
|
||||
];
|
||||
|
||||
$filename = 'matab-backup-' . now()->format('Y-m-d_H-i-s') . '.json';
|
||||
|
||||
return response()->streamDownload(function () use ($data) {
|
||||
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}, $filename, ['Content-Type' => 'application/json']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user