Merge pull request #11 from truncgil/app-setting-seeders

App setting seeders
This commit is contained in:
Truncgil Technology
2025-10-30 21:28:11 +03:00
committed by GitHub
9 changed files with 1294 additions and 71 deletions
@@ -0,0 +1,29 @@
<?php
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// Settings seed
$this->call([
SettingSeeder::class,
]);
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
}
}
+86 -6
View File
@@ -102,11 +102,85 @@ use Filament\Forms\Components\FileUpload;
use Filament\Schemas\Components\Section; // ✅ Doğru
use Filament\Schemas\Components\Grid; // ✅ Doğru
use Filament\Schemas\Components\Fieldset; // ✅ Doğru
use Filament\Schemas\Components\Flex; // ✅ Doğru
// Tabs components (ÖNEMLİ: Forms namespace!)
use Filament\Forms\Components\Tabs; // ✅ Doğru
// Tab kullanımı: Tabs\Tab::make() şeklinde kullan
// Import gerekmez, Tabs namespace'i üzerinden erişilir
// Tabs components (ÖNEMLİ: Schemas namespace!)
use Filament\Schemas\Components\Tabs; // ✅ Doğru
use Filament\Schemas\Components\Tabs\Tab; // ✅ Doğru
// FORM/INFOLIST içindeki tab'lar için yukarıdaki import'ları kullan
// Wizard component (Schemas namespace!)
use Filament\Schemas\Components\Wizard;
use Filament\Schemas\Components\Wizard\Step;
// Infolist entry components
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\IconEntry;
use Filament\Infolists\Components\ImageEntry;
```
#### **Filament 4.x TAB KULLANIM KURALLARI (KRİTİK!):**
Filament 4.x'te **iki farklı Tab sistemi** vardır:
**1. Resource List Pages Tabs (getTabs() metodu):**
```php
// ❌ YANLIŞ - Bu class Filament 4.x'te YOK!
use Filament\Resources\Components\Tab;
// ✅ DOĞRU - ListRecords page'lerinde getTabs() için
use Filament\Schemas\Components\Tabs\Tab;
// Örnek kullanım:
class ListSettings extends ListRecords
{
public function getTabs(): array
{
return [
'all' => Tab::make('Tümü')
->icon('heroicon-o-squares-2x2')
->badge(100)
->modifyQueryUsing(fn (Builder $query) => $query),
'active' => Tab::make('Aktif')
->icon('heroicon-o-check')
->badge(50)
->modifyQueryUsing(fn (Builder $query) => $query->where('is_active', true)),
];
}
}
```
**2. Form/Schema Tabs (Form içinde kullanım):**
```php
// ✅ DOĞRU - Form/Schema içinde tabs için
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
// Örnek kullanım:
public static function form(Schema $schema): Schema
{
return $schema
->components([
Tabs::make('Tabs')
->tabs([
Tab::make('Genel Bilgiler')
->icon('heroicon-o-information-circle')
->schema([
TextInput::make('name'),
// ...
]),
Tab::make('SEO')
->icon('heroicon-o-magnifying-glass')
->schema([
TextInput::make('meta_title'),
// ...
]),
])
->columnSpanFull()
->persistTabInQueryString(),
]);
}
```
#### **YANLIŞ KULLANIM (Eski Filament 3.x):**
@@ -115,6 +189,8 @@ use Filament\Forms\Components\Tabs; // ✅ Doğru
use Filament\Tables\Actions\EditAction; // ❌
use Filament\Forms\Components\Section; // ❌
use Filament\Forms\Components\Grid; // ❌
use Filament\Forms\Components\Tabs; // ❌ Forms namespace altında Tabs YOK
use Filament\Resources\Components\Tab; // ❌ Bu class hiç YOK
// ❌ YANLIŞ - Eski metod adları
$table
@@ -122,14 +198,18 @@ $table
->bulkActions([...]) // ❌ Kullanma!
```
#### **ÖZET:**
#### **ÖZET (Filament 4.x Import Referansı):**
- ✅ **Table Actions:** `Filament\Actions\` namespace
- ✅ **Table Columns:** `Filament\Tables\Columns\` namespace
- ✅ **Table Filters:** `Filament\Tables\Filters\` namespace
- ✅ **Form Inputs:** `Filament\Forms\Components\` namespace
- ✅ **Layout Components:** `Filament\Schemas\Components\` namespace (Section, Grid, Tabs)
- ✅ **Layout Components:** `Filament\Schemas\Components\` namespace
- ✅ **Tabs (Tüm Kullanımlar):** `Filament\Schemas\Components\Tabs\Tab` (Her yerde bu!)
- ✅ **Infolist Entries:** `Filament\Infolists\Components\` namespace
- ✅ **Table Methods:** `->recordActions()` ve `->toolbarActions()`
**Önemli Not:** Filament 4.x'te `Filament\Resources\Components\Tab` diye bir class **YOK**. Tüm tab kullanımları `Filament\Schemas\Components\Tabs\Tab` ile yapılır!
### Dil Dosyası Yapısı
<?php
@@ -3,8 +3,13 @@
namespace App\Filament\Admin\Resources\Settings\Pages;
use App\Filament\Admin\Resources\Settings\SettingResource;
use App\Models\Setting;
use Filament\Actions\CreateAction;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Resources\Pages\ListRecords;
use Filament\Support\Enums\Width;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Builder;
class ListSettings extends ListRecords
{
@@ -15,6 +20,11 @@ class ListSettings extends ListRecords
return __('settings.title');
}
public function getHeading(): string | Htmlable
{
return __('settings.title');
}
protected function getHeaderActions(): array
{
return [
@@ -22,4 +32,65 @@ class ListSettings extends ListRecords
->label(__('settings.create')),
];
}
public function getMaxContentWidth(): Width | string | null
{
return Width::Full;
}
public function getTabs(): array
{
$tabs = [];
// "Tüm Ayarlar" tab'ı ekle
$allCount = Setting::query()->count();
$tabs['all'] = Tab::make(__('settings.all_settings'))
->icon($this->getGroupIcon(null))
->badge($allCount);
// Her grup için tab oluştur
$groups = Setting::query()
->select('group')
->distinct()
->orderBy('group')
->pluck('group');
foreach ($groups as $group) {
$count = Setting::where('group', $group)->count();
$label = __("settings.group_{$group}");
$tabs[$group] = Tab::make($label)
->icon($this->getGroupIcon($group))
->badge($count)
->modifyQueryUsing(fn (Builder $query) => $query->where('group', $group));
}
return $tabs;
}
protected function getGroupIcon(?string $group): string
{
if (!$group) {
return 'heroicon-o-squares-2x2';
}
return match($group) {
'general' => 'heroicon-o-cog-6-tooth',
'theme' => 'heroicon-o-paint-brush',
'localization' => 'heroicon-o-language',
'email' => 'heroicon-o-envelope',
'seo' => 'heroicon-o-magnifying-glass',
'social' => 'heroicon-o-share',
'security' => 'heroicon-o-shield-check',
'upload' => 'heroicon-o-cloud-arrow-up',
'payment' => 'heroicon-o-credit-card',
'notification' => 'heroicon-o-bell',
'cache' => 'heroicon-o-arrow-path',
'api' => 'heroicon-o-code-bracket',
'logging' => 'heroicon-o-document-text',
'performance' => 'heroicon-o-bolt',
'integration' => 'heroicon-o-puzzle-piece',
default => 'heroicon-o-squares-2x2',
};
}
}
@@ -92,12 +92,20 @@ class SettingForm
->required()
->options([
'general' => __('settings.group_general'),
'theme' => __('settings.group_theme'),
'localization' => __('settings.group_localization'),
'email' => __('settings.group_email'),
'seo' => __('settings.group_seo'),
'social' => __('settings.group_social'),
'security' => __('settings.group_security'),
'upload' => __('settings.group_upload'),
'payment' => __('settings.group_payment'),
'notification' => __('settings.group_notification'),
'cache' => __('settings.group_cache'),
'api' => __('settings.group_api'),
'logging' => __('settings.group_logging'),
'performance' => __('settings.group_performance'),
'integration' => __('settings.group_integration'),
'other' => __('settings.group_other'),
])
->default('general'),
@@ -58,13 +58,14 @@ class SettingsTable
default => 'gray',
})
->formatStateUsing(fn (string $state): string => __("settings.type_{$state}")),
TextColumn::make('group')
->label(__('settings.table_group'))
->badge()
->color('primary')
->visible(fn ($livewire) => $livewire->activeTab === 'all')
->formatStateUsing(fn (string $state): string => __("settings.group_{$state}")),
IconColumn::make('is_active')
->label(__('settings.table_active'))
->boolean()
@@ -88,19 +89,6 @@ class SettingsTable
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
SelectFilter::make('group')
->label(__('settings.filter_group'))
->options([
'general' => __('settings.group_general'),
'email' => __('settings.group_email'),
'seo' => __('settings.group_seo'),
'social' => __('settings.group_social'),
'security' => __('settings.group_security'),
'payment' => __('settings.group_payment'),
'notification' => __('settings.group_notification'),
'other' => __('settings.group_other'),
]),
SelectFilter::make('type')
->label(__('settings.filter_type'))
->options([
+5
View File
@@ -13,6 +13,11 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
// Settings seed
$this->call([
SettingSeeder::class,
]);
// User::factory(10)->create();
User::factory()->create([
File diff suppressed because it is too large Load Diff
+13
View File
@@ -75,12 +75,20 @@ return [
// Groups
'group_general' => 'General',
'group_theme' => 'Theme',
'group_localization' => 'Localization',
'group_email' => 'Email',
'group_seo' => 'SEO',
'group_social' => 'Social Media',
'group_security' => 'Security',
'group_upload' => 'Upload',
'group_payment' => 'Payment',
'group_notification' => 'Notification',
'group_cache' => 'Cache',
'group_api' => 'API',
'group_logging' => 'Logging',
'group_performance' => 'Performance',
'group_integration' => 'Integration',
'group_other' => 'Other',
// Validation messages
@@ -121,5 +129,10 @@ return [
'filter_type' => 'By Type',
'filter_active' => 'Active',
'filter_public' => 'Public',
// Tabs
'tabs_title' => 'Setting Groups',
'settings_count' => 'settings',
'all_settings' => 'All Settings',
];
+13
View File
@@ -75,12 +75,20 @@ return [
// Groups
'group_general' => 'Genel',
'group_theme' => 'Tema',
'group_localization' => 'Lokalizasyon',
'group_email' => 'E-posta',
'group_seo' => 'SEO',
'group_social' => 'Sosyal Medya',
'group_security' => 'Güvenlik',
'group_upload' => 'Dosya Yükleme',
'group_payment' => 'Ödeme',
'group_notification' => 'Bildirim',
'group_cache' => 'Cache',
'group_api' => 'API',
'group_logging' => 'Logging',
'group_performance' => 'Performans',
'group_integration' => 'Entegrasyon',
'group_other' => 'Diğer',
// Validation messages
@@ -121,5 +129,10 @@ return [
'filter_type' => 'Tipe Göre',
'filter_active' => 'Aktif',
'filter_public' => 'Herkese Açık',
// Tabs
'tabs_title' => 'Ayar Grupları',
'settings_count' => 'ayar',
'all_settings' => 'Tüm Ayarlar',
];