diff --git a/database/migrations/add_columns_to_redirects_table_for_backstage.php.stub b/database/migrations/add_columns_to_redirects_table_for_backstage.php.stub new file mode 100644 index 0000000..2ad7fe0 --- /dev/null +++ b/database/migrations/add_columns_to_redirects_table_for_backstage.php.stub @@ -0,0 +1,25 @@ +after('ulid', function ($table) { + $table->foreignUlid('site_ulid')->nullable()->constrained(table: 'sites', column: 'ulid')->cascadeOnUpdate()->cascadeOnDelete(); + $table->char('language_code', 2)->nullable(); + $table->char('country_code', 2)->nullable(); + $table->foreignUlid('content_ulid')->nullable()->constrained(table: 'content', column: 'ulid')->cascadeOnUpdate()->cascadeOnDelete(); + }); + + $table->foreign(['language_code', 'country_code'])->references(['code', 'country_code'])->on('languages')->cascadeOnUpdate()->nullOnDelete(); + }); + } +}; diff --git a/database/migrations/create_redirects_table_filament.php.stub b/database/migrations/create_redirects_table_filament.php.stub deleted file mode 100644 index d50884c..0000000 --- a/database/migrations/create_redirects_table_filament.php.stub +++ /dev/null @@ -1,23 +0,0 @@ -foreignUlid('site_ulid')->nullable()->constrained(table: 'sites', column: 'ulid')->cascadeOnUpdate()->cascadeOnDelete()->after('ulid'); - $table->char('language_code', 2)->nullable()->after('site_ulid'); - $table->char('country_code', 2)->nullable()->after('language_code'); - $table->foreignUlid('content_ulid')->nullable()->constrained(table: 'content', column: 'ulid')->cascadeOnUpdate()->cascadeOnDelete()->after('path'); - - $table->foreign(['language_code', 'country_code'])->references(['code', 'country_code'])->on('languages')->cascadeOnUpdate()->nullOnDelete(); - }); - } -}; diff --git a/src/FilamentRedirects.php b/src/FilamentRedirects.php deleted file mode 100644 index e25a986..0000000 --- a/src/FilamentRedirects.php +++ /dev/null @@ -1,5 +0,0 @@ -name(static::$name) ->hasCommands($this->getCommands()) ->hasInstallCommand(function (InstallCommand $command) { @@ -101,8 +96,8 @@ protected function getAssets(): array { return [ // AlpineComponent::make('filament-redirects', __DIR__ . '/../resources/dist/components/filament-redirects.js'), - Css::make('filament-redirects-styles', __DIR__ . '/../resources/dist/filament-redirects.css'), - Js::make('filament-redirects-scripts', __DIR__ . '/../resources/dist/filament-redirects.js'), + // Css::make('filament-redirects-styles', __DIR__ . '/../resources/dist/filament-redirects.css'), + // Js::make('filament-redirects-scripts', __DIR__ . '/../resources/dist/filament-redirects.js'), ]; } @@ -146,7 +141,7 @@ protected function getScriptData(): array protected function getMigrations(): array { return [ - 'create_filament-redirects_table', + 'add_columns_to_redirects_table_for_backstage', ]; } } diff --git a/src/Imports/RedirectImporter.php b/src/Imports/RedirectImporter.php new file mode 100644 index 0000000..508124a --- /dev/null +++ b/src/Imports/RedirectImporter.php @@ -0,0 +1,75 @@ +label(__('Site')) + ->requiredMapping() + ->guess(['site', 'site_ulid']), + ImportColumn::make('language_code') + ->label(__('Language Code')) + ->requiredMapping() + ->guess(['language', 'language_code']), + ImportColumn::make('country_code') + ->label(__('Country Code')) + ->guess(['KvKnr']), + ImportColumn::make('content_ulid') + ->label(__('Content')) + ->requiredMapping() + ->guess(['content', 'content_ulid']), + ImportColumn::make('source') + ->requiredMapping() + ->label(__('Source')) + ->guess(['source']), + ImportColumn::make('destination') + ->requiredMapping() + ->label(__('Destination')) + ->guess(['destination']), + ImportColumn::make('code') + ->requiredMapping() + ->rules(['max:3']) + ->guess(['code', 'status', 'status_code']), + ImportColumn::make('hits') + ->requiredMapping() + ->guess(['hits']), + ]; + } + + public function resolveRecord(): ?Redirect + { + if (isset($this->data['source'])) { + return Redirect::firstOrNew([ + 'source' => $this->data['source'], + ]); + } + } + + public static function getCompletedNotificationBody(Import $import): string + { + $body = __('Your redirects import has completed and :numbers :row imported.', [ + 'numbers' => number_format($import->successful_rows), + 'row' => str('row')->plural($import->successful_rows), + ]); + + if ($failedRowsCount = $import->getFailedRowsCount()) { + $body .= __(' :numbers :row failed to import.', [ + 'numbers' => number_format($failedRowsCount), + 'row' => str('row')->plural($failedRowsCount), + ]); + } + + return $body; + } +} diff --git a/src/Middleware/MatchRedirects.php b/src/Middleware/MatchRedirects.php new file mode 100644 index 0000000..4128aa5 --- /dev/null +++ b/src/Middleware/MatchRedirects.php @@ -0,0 +1,5 @@ +resources([ + RedirectResource::class, + ]); } public function boot(Panel $panel): void diff --git a/src/Resources/RedirectResource.php b/src/Resources/RedirectResource.php index 09ad44a..0ed935b 100644 --- a/src/Resources/RedirectResource.php +++ b/src/Resources/RedirectResource.php @@ -2,13 +2,20 @@ namespace Vormkracht10\FilamentRedirects\Resources; +use Locale; +use Filament\Tables; use Filament\Forms\Form; +use Filament\Tables\Table; use Filament\Resources\Resource; -use Filament\Tables; +use Filament\Forms\Components\Select; +use Filament\Forms\Components\Section; +use Illuminate\Support\Facades\Schema; use Filament\Tables\Columns\TextColumn; -use Filament\Tables\Table; +use Vormkracht10\Backstage\Models\Site; +use Filament\Forms\Components\TextInput; +use Vormkracht10\Backstage\Models\Language; use Vormkracht10\Redirects\Models\Redirect; -use Vormkracht10\Backstage\Resources\RedirectResource\Pages; +use Vormkracht10\FilamentRedirects\Resources\RedirectResource\Pages; class RedirectResource extends Resource { @@ -18,6 +25,8 @@ class RedirectResource extends Resource public static ?string $recordTitleAttribute = 'name'; + protected static ?int $navigationSort = 10; + public static function getModelLabel(): string { return __('Redirect'); @@ -31,14 +40,89 @@ public static function getPluralModelLabel(): string public static function form(Form $form): Form { return $form - ->schema([]); + ->schema([ + Section::make('From') + ->columns([ + 'sm' => 1, + 'md' => 12, + ]) + ->schema([ + Select::make('site_ulid') + ->label(__('Site')) + ->columnSpan(4) + ->placeholder(__('Select Site')) + ->prefixIcon('heroicon-o-link') + ->options(Site::orderBy('default', 'desc')->orderBy('name', 'asc')->pluck('name', 'ulid')) + ->default(Site::where('default', true)->first()?->ulid) + ->visible(fn() => Schema::hasColumn('redirects', 'content_ulid') && Site::count() > 0) + ->hidden(fn() => Schema::hasColumn('redirects', 'content_ulid') && Site::count() === 1), + Select::make('country_code') + ->label(__('Country')) + ->columnSpan(4) + ->placeholder(__('Select Country')) + ->prefixIcon('heroicon-o-flag') + ->options(Language::whereNotNull('country_code')->distinct('country_code')->get()->mapWithKeys(fn($language) => [$language->country_code => Locale::getDisplayRegion('-' . $language->country_code, app()->getLocale())])->sort()) + ->default(Language::whereNotNull('country_code')->distinct('country_code')->count() === 1 ? Language::whereNotNull('country_code')->first()->country_code : null) + ->visible(fn() => Schema::hasColumn('redirects', 'content_ulid') && Language::whereNotNull('country_code')->distinct('country_code')->count() > 0) + ->hidden(fn() => Schema::hasColumn('redirects', 'content_ulid') && Language::whereNotNull('country_code')->distinct('country_code')->count() === 1), + Select::make('language_code') + ->label(__('Language')) + ->columnSpan(4) + ->placeholder(__('Select Language')) + ->prefixIcon('heroicon-o-language') + ->options(Language::get()->mapWithKeys(fn($language) => [$language->code => Locale::getDisplayLanguage($language->code, app()->getLocale())])->sort()) + ->default(Language::count() === 1 ? Language::first()->code : Language::where('default', true)->first()->code) + ->visible(fn() => Schema::hasColumn('redirects', 'content_ulid') && Language::count() > 0) + ->hidden(fn() => Schema::hasColumn('redirects', 'content_ulid') && Language::count() === 1), + TextInput::make('source') + ->label(__('Source')) + ->columnSpan(12) + ->required() + ->prefixIcon('heroicon-o-arrow-uturn-right') + ->placeholder(__('Type path, URL or pattern...')) + ->helperText(__('The path to match, you can use regular expressions.')), + ]), + Section::make('To') + ->columns([ + 'sm' => 1, + 'md' => 12, + ]) + ->schema([ + Select::make('code') + ->label(__('Type')) + ->columnSpan(4) + ->native(false) + ->options(collect(config('redirects.status_codes'))->map(fn(string $type, int $code) => $type . ' (' . $code . ')')) + ->searchable() + ->required() + ->default(config('redirects.default_status_code')) + ->prefixIcon('heroicon-o-hashtag') + ->placeholder('HTTP status message'), + Select::make('content') + ->label(__('Content')) + ->columnSpan(8) + ->placeholder('Content') + ->prefixIcon('heroicon-o-link') + ->helperText(__('Select a content page to redirect to the current URL.')) + ->visible(fn() => Schema::hasColumn('redirects', 'content_ulid')), + TextInput::make('destination') + ->label(__('Destination')) + ->columnSpan(12) + ->required() + ->prefixIcon('heroicon-o-arrow-uturn-left') + ->placeholder('Type path or URL...'), + ]), + ]); } public static function table(Table $table): Table { return $table ->columns([ - TextColumn::make('path') + TextColumn::make('source') + ->searchable() + ->sortable(), + TextColumn::make('destination') ->searchable() ->sortable(), ]) diff --git a/src/Resources/RedirectResource/Pages/CreateRedirect.php b/src/Resources/RedirectResource/Pages/CreateRedirect.php index 7a2c384..9ec24d5 100644 --- a/src/Resources/RedirectResource/Pages/CreateRedirect.php +++ b/src/Resources/RedirectResource/Pages/CreateRedirect.php @@ -3,7 +3,7 @@ namespace Vormkracht10\FilamentRedirects\Resources\RedirectResource\Pages; use Filament\Resources\Pages\CreateRecord; -use Vormkracht10\Backstage\Resources\RedirectResource; +use Vormkracht10\FilamentRedirects\Resources\RedirectResource; class CreateRedirect extends CreateRecord { diff --git a/src/Resources/RedirectResource/Pages/EditRedirect.php b/src/Resources/RedirectResource/Pages/EditRedirect.php index 43f89c4..368c99d 100644 --- a/src/Resources/RedirectResource/Pages/EditRedirect.php +++ b/src/Resources/RedirectResource/Pages/EditRedirect.php @@ -4,7 +4,7 @@ use Filament\Actions; use Filament\Resources\Pages\EditRecord; -use Vormkracht10\Backstage\Resources\RedirectResource; +use Vormkracht10\FilamentRedirects\Resources\RedirectResource; class EditRedirect extends EditRecord { diff --git a/src/Resources/RedirectResource/Pages/ListRedirects.php b/src/Resources/RedirectResource/Pages/ListRedirects.php index 25a5dc0..5acbcb6 100644 --- a/src/Resources/RedirectResource/Pages/ListRedirects.php +++ b/src/Resources/RedirectResource/Pages/ListRedirects.php @@ -4,7 +4,8 @@ use Filament\Actions; use Filament\Resources\Pages\ListRecords; -use Vormkracht10\Backstage\Resources\RedirectResource; +use Vormkracht10\FilamentRedirects\Imports\RedirectImporter; +use Vormkracht10\FilamentRedirects\Resources\RedirectResource; class ListRedirects extends ListRecords { @@ -13,6 +14,9 @@ class ListRedirects extends ListRecords protected function getHeaderActions(): array { return [ + Actions\ImportAction::make() + ->label(__('Import')) + ->importer(RedirectImporter::class), Actions\CreateAction::make(), ]; }