From 91922ac6bf3726403ae8ac673132ecfa0be86c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Cmit=20Tun=C3=A7?= Date: Wed, 5 Nov 2025 09:39:02 -0300 Subject: [PATCH] Add bulk actions for page management: Implemented duplicate and publish functionalities in the PagesTable, allowing users to duplicate selected pages and publish them in bulk. Added corresponding localization keys for English and Turkish languages to enhance user experience. --- .../Resources/Pages/Tables/PagesTable.php | 41 ++++++++++++++++ app/Models/Page.php | 48 +++++++++++++++++++ lang/en/pages.php | 6 +++ lang/tr/pages.php | 6 +++ 4 files changed, 101 insertions(+) diff --git a/app/Filament/Admin/Resources/Pages/Tables/PagesTable.php b/app/Filament/Admin/Resources/Pages/Tables/PagesTable.php index 769df06..0a8e91e 100644 --- a/app/Filament/Admin/Resources/Pages/Tables/PagesTable.php +++ b/app/Filament/Admin/Resources/Pages/Tables/PagesTable.php @@ -2,11 +2,13 @@ namespace App\Filament\Admin\Resources\Pages\Tables; +use Filament\Actions\BulkAction; use Filament\Actions\BulkActionGroup; use Filament\Actions\DeleteBulkAction; use Filament\Actions\EditAction; use Filament\Actions\ForceDeleteBulkAction; use Filament\Actions\RestoreBulkAction; +use Filament\Notifications\Notification; use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\ImageColumn; use Filament\Tables\Columns\TextColumn; @@ -120,6 +122,45 @@ class PagesTable ]) ->toolbarActions([ BulkActionGroup::make([ + BulkAction::make('duplicate') + ->label(__('pages.bulk_action_duplicate')) + ->icon('heroicon-o-document-duplicate') + ->color('info') + ->action(function ($records) { + $count = 0; + foreach ($records as $record) { + $record->duplicate(); + $count++; + } + + Notification::make() + ->title(__('pages.bulk_duplicated_successfully', ['count' => $count])) + ->success() + ->send(); + }) + ->requiresConfirmation() + ->deselectRecordsAfterCompletion(), + + BulkAction::make('publish') + ->label(__('pages.bulk_action_publish')) + ->icon('heroicon-o-check-circle') + ->color('success') + ->action(function ($records) { + $count = 0; + foreach ($records as $record) { + if ($record->publish()) { + $count++; + } + } + + Notification::make() + ->title(__('pages.bulk_published_successfully', ['count' => $count])) + ->success() + ->send(); + }) + ->requiresConfirmation() + ->deselectRecordsAfterCompletion(), + DeleteBulkAction::make(), ForceDeleteBulkAction::make(), RestoreBulkAction::make(), diff --git a/app/Models/Page.php b/app/Models/Page.php index 38fe29b..6f7365a 100644 --- a/app/Models/Page.php +++ b/app/Models/Page.php @@ -196,4 +196,52 @@ class Page extends Model { return null; // Mevcut migration nullable olduğu için null kullanıyoruz } + + /** + * Duplicate the page + */ + public function duplicate(): self + { + $duplicated = $this->replicate(); + + // Generate unique slug + $baseSlug = $this->slug; + $counter = 1; + do { + $newSlug = $baseSlug . '-copy-' . $counter; + $counter++; + } while (static::where('slug', $newSlug)->exists()); + + $duplicated->slug = $newSlug; + $duplicated->title = $this->title . ' (Kopya)'; + $duplicated->status = 'draft'; + $duplicated->published_at = null; + $duplicated->is_homepage = false; // Duplicate can't be homepage + $duplicated->author_id = auth()->id(); + $duplicated->save(); + + // Duplicate translations if HasTranslations trait is used + if (method_exists($this, 'translations')) { + foreach ($this->translations()->get() as $translation) { + $duplicatedTranslation = $translation->replicate(); + $duplicatedTranslation->translatable_type = get_class($duplicated); + $duplicatedTranslation->translatable_id = $duplicated->id; + $duplicatedTranslation->save(); + } + } + + return $duplicated; + } + + /** + * Publish the page + */ + public function publish(): bool + { + $this->status = 'published'; + if (!$this->published_at) { + $this->published_at = now(); + } + return $this->save(); + } } diff --git a/lang/en/pages.php b/lang/en/pages.php index 960b536..39e4382 100644 --- a/lang/en/pages.php +++ b/lang/en/pages.php @@ -170,4 +170,10 @@ return [ 'form_section_footer_template' => 'Footer Template', 'form_section_footer_template_desc' => 'Select a dynamic footer template for the bottom of the page', 'footer_template_field' => 'Footer Template', + + // Bulk Actions + 'bulk_action_duplicate' => 'Duplicate Selected', + 'bulk_action_publish' => 'Publish Selected', + 'bulk_duplicated_successfully' => ':count page(s) duplicated successfully.', + 'bulk_published_successfully' => ':count page(s) published successfully.', ]; diff --git a/lang/tr/pages.php b/lang/tr/pages.php index 286d674..f0df88e 100644 --- a/lang/tr/pages.php +++ b/lang/tr/pages.php @@ -170,4 +170,10 @@ return [ 'form_section_footer_template' => 'Footer Şablonu', 'form_section_footer_template_desc' => 'Sayfanın alt kısmı için dinamik footer şablonu seçin', 'footer_template_field' => 'Footer Şablonu', + + // Bulk Actions + 'bulk_action_duplicate' => 'Seçilenleri Çoğalt', + 'bulk_action_publish' => 'Seçilenleri Yayınla', + 'bulk_duplicated_successfully' => ':count sayfa başarıyla çoğaltıldı.', + 'bulk_published_successfully' => ':count sayfa başarıyla yayınlandı.', ];