From 5d1943baf0f37c8619373deed68309d6ba14706f Mon Sep 17 00:00:00 2001 From: Nick Rogers Date: Tue, 12 Mar 2024 16:45:45 +1030 Subject: [PATCH 1/3] feature: expose slugs to authors, transform data, then redirect feature: improve layout of AbstractContentResource form chore: add prettierrc --- .prettierrc | 4 + .../components/forms/status-badge.blade.php | 8 ++ src/Events/ContentUpdating.php | 6 +- src/Filament/Forms/Components/StatusBadge.php | 19 ++++ .../Resources/AbstractContentResource.php | 107 ++++++++++++++---- .../Pages/CreateAbstractContentResource.php | 8 ++ .../Pages/EditAbstractContentResource.php | 13 +++ views/components/hr.blade.php | 1 + 8 files changed, 146 insertions(+), 20 deletions(-) create mode 100644 .prettierrc create mode 100644 resources/views/components/forms/status-badge.blade.php create mode 100644 src/Filament/Forms/Components/StatusBadge.php create mode 100644 views/components/hr.blade.php diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..9b79f387 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 4, + "useTabs": false +} \ No newline at end of file diff --git a/resources/views/components/forms/status-badge.blade.php b/resources/views/components/forms/status-badge.blade.php new file mode 100644 index 00000000..b51187aa --- /dev/null +++ b/resources/views/components/forms/status-badge.blade.php @@ -0,0 +1,8 @@ + +
+ + + {{ $getState() }} + +
+
diff --git a/src/Events/ContentUpdating.php b/src/Events/ContentUpdating.php index fce14115..402ee284 100644 --- a/src/Events/ContentUpdating.php +++ b/src/Events/ContentUpdating.php @@ -6,6 +6,7 @@ use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Carbon; +use Illuminate\Support\Str; use Portable\FilaCms\Models\AbstractContentModel; class ContentUpdating @@ -20,9 +21,12 @@ class ContentUpdating public function __construct(public AbstractContentModel $page) { $page->updated_user_id = auth()->user() ? auth()->user()->id : $page->created_user_id; - if(!$page->is_draft && is_null($page->publish_at)) { + if (!$page->is_draft && is_null($page->publish_at)) { $page->publish_at = Carbon::now()->subMinute(); } + if ($page->slug === null) { + $page->slug = Str::slug($page->title); + } } } diff --git a/src/Filament/Forms/Components/StatusBadge.php b/src/Filament/Forms/Components/StatusBadge.php new file mode 100644 index 00000000..df0c78b6 --- /dev/null +++ b/src/Filament/Forms/Components/StatusBadge.php @@ -0,0 +1,19 @@ +label('Draft?') - ->offIcon('heroicon-m-eye') - ->onIcon('heroicon-m-eye-slash')->columnSpanFull(), - TextInput::make('title') - ->required(), - Select::make('author_id') - ->label('Author') - ->options(Author::all()->pluck('display_name', 'id')) - ->searchable(), - DatePicker::make('publish_at') - ->label('Publish Date'), - DatePicker::make('expire_at') - ->label('Expiry Date'), - static::tiptapEditor(), + Group::make() + ->schema([ + Tabs::make() + ->tabs([ + Tabs\Tab::make('Content') + ->schema([ + + TextInput::make('title') + ->columnSpanFull() + ->required(), + static::tiptapEditor(), + ]), + Tabs\Tab::make('Taxonomies') + ->schema([ + ...static::getTaxonomyFields(), + ]), + ]), + ]) + ->columnSpan(2), + Group::make() + ->schema([ + Section::make() + ->schema([ + TextInput::make('slug') + ->maxLength(255), + Toggle::make('is_draft') + ->label('Draft?') + ->offIcon('heroicon-m-eye') + ->onIcon('heroicon-m-eye-slash')->columnSpanFull(), + Select::make('author_id') + ->label('Author') + ->options(Author::all()->pluck('display_name', 'id')) + ->searchable(), + View::make('fila-cms::components.hr'), + DatePicker::make('publish_at') + ->label('Publish Date') + ->live(), + DatePicker::make('expire_at') + ->label('Expiry Date'), + ]) + ->columns(1), + Fieldset::make() + ->schema([ + Placeholder::make('publish_at_view') + ->label('Published') + ->visible(fn (?Model $record): bool => $record && $record->status === 'Published') + ->content(function (?Model $record): string { + return $record->publish_at ?? '?'; + }), + Placeholder::make('created_at_view') + ->label('Created') + ->visible(fn (?Model $record): bool => $record !== null) + ->content(function (?Model $record): string { + return $record->created_at ?? '?'; + }), + StatusBadge::make('status') + ->live() + ->badge() + ->color(fn (string $state): string => match ($state) { + 'Draft' => 'info', + 'Pending' => 'warning', + 'Published' => 'success', + 'Expired' => 'danger', + }) + ->default('Draft'), + + ]) + ->columns(1) + ]) + ->columnSpan(1), ]; - TaxonomyResource::where('resource_class', static::class)->get()->each(function (TaxonomyResource $taxonomyResource) use (&$fields) { + return $form->schema($fields)->columns(['lg' => 3]); + } + + public static function getTaxonomyFields(): array + { + $taxonomyFields = []; + TaxonomyResource::where('resource_class', static::class)->get()->each(function (TaxonomyResource $taxonomyResource) use (&$taxonomyFields) { $fieldName = Str::slug(Str::plural($taxonomyResource->taxonomy->name), '_'); - $fields[] = CheckboxList::make($fieldName.'_ids') + $taxonomyFields[] = CheckboxList::make($fieldName . '_ids') ->label($taxonomyResource->taxonomy->name) ->options($taxonomyResource->taxonomy->terms->pluck('name', 'id')); }); - return $form->schema($fields); + return $taxonomyFields; } public static function tiptapEditor($name = 'contents'): TiptapEditor @@ -85,7 +154,7 @@ public static function table(Table $table): Table return $table ->columns([ TextColumn::make('title') - ->description(fn (Page $page): string => substr($page->contents, 0, 50).'...') + ->description(fn (Page $page): string => substr($page->contents, 0, 50) . '...') ->sortable(), TextColumn::make('author.display_name')->label('Author') ->sortable(), diff --git a/src/Filament/Resources/AbstractContentResource/Pages/CreateAbstractContentResource.php b/src/Filament/Resources/AbstractContentResource/Pages/CreateAbstractContentResource.php index 84f5c503..4179397a 100644 --- a/src/Filament/Resources/AbstractContentResource/Pages/CreateAbstractContentResource.php +++ b/src/Filament/Resources/AbstractContentResource/Pages/CreateAbstractContentResource.php @@ -3,9 +3,17 @@ namespace Portable\FilaCms\Filament\Resources\AbstractContentResource\Pages; use Filament\Resources\Pages\CreateRecord; +use Illuminate\Support\Str; use Portable\FilaCms\Filament\Resources\AbstractContentResource; class CreateAbstractContentResource extends CreateRecord { protected static string $resource = AbstractContentResource::class; + + protected function mutateFormDataBeforeCreate(array $data): array + { + $data['slug'] = $data['slug'] ? Str::slug($data['slug']) : null; + + return $data; + } } diff --git a/src/Filament/Resources/AbstractContentResource/Pages/EditAbstractContentResource.php b/src/Filament/Resources/AbstractContentResource/Pages/EditAbstractContentResource.php index e7d37c4d..353c8245 100644 --- a/src/Filament/Resources/AbstractContentResource/Pages/EditAbstractContentResource.php +++ b/src/Filament/Resources/AbstractContentResource/Pages/EditAbstractContentResource.php @@ -4,6 +4,7 @@ use Filament\Actions; use Filament\Resources\Pages\EditRecord; +use Illuminate\Support\Str; use Portable\FilaCms\Filament\Resources\AbstractContentResource; class EditAbstractContentResource extends EditRecord @@ -16,4 +17,16 @@ protected function getHeaderActions(): array Actions\DeleteAction::make(), ]; } + + protected function mutateFormDataBeforeSave(array $data): array + { + $data['slug'] = $data['slug'] ? Str::slug($data['slug']) : null; + + return $data; + } + + protected function getRedirectUrl(): string + { + return $this->getResource()::getUrl('edit', ['record' => $this->record]); + } } diff --git a/views/components/hr.blade.php b/views/components/hr.blade.php new file mode 100644 index 00000000..23471aa6 --- /dev/null +++ b/views/components/hr.blade.php @@ -0,0 +1 @@ +
From 7c98c5076273035a464b15c96325678fd65ed382 Mon Sep 17 00:00:00 2001 From: Nick Rogers Date: Wed, 13 Mar 2024 01:36:57 +1030 Subject: [PATCH 2/3] style: fix formatting test: add update_sets_slug chore: swap to .editorconfig --- .editorconfig | 18 +++++++++++++ .prettierrc | 4 --- src/Filament/Forms/Components/StatusBadge.php | 4 --- tests/Unit/PageEventsTest.php | 25 +++++++++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 .editorconfig delete mode 100644 .prettierrc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..8f0de65c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 + +[docker-compose.yml] +indent_size = 4 diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 9b79f387..00000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "tabWidth": 4, - "useTabs": false -} \ No newline at end of file diff --git a/src/Filament/Forms/Components/StatusBadge.php b/src/Filament/Forms/Components/StatusBadge.php index df0c78b6..bb2eabb0 100644 --- a/src/Filament/Forms/Components/StatusBadge.php +++ b/src/Filament/Forms/Components/StatusBadge.php @@ -5,15 +5,11 @@ use Filament\Forms\Components\Field; use Filament\Support\Concerns\HasBadge; use Filament\Support\Concerns\HasColor; -use Illuminate\Database\Eloquent\Model; class StatusBadge extends Field { - use HasBadge; use HasColor; - // protected string $view = 'forms.components.status-badge'; - public const BADGE_VIEW = 'forms.components.status-badge'; } diff --git a/tests/Unit/PageEventsTest.php b/tests/Unit/PageEventsTest.php index 8b55c74b..784e3669 100644 --- a/tests/Unit/PageEventsTest.php +++ b/tests/Unit/PageEventsTest.php @@ -4,6 +4,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Support\Str; use Portable\FilaCms\Models\Author; use Portable\FilaCms\Models\Page; use Portable\FilaCms\Tests\TestCase; @@ -53,4 +54,28 @@ public function test_update_sets_publish() $page->save(); $this->assertNotNull($page->publish_at); } + + public function test_update_sets_slug() + { + $author = Author::create([ + 'first_name' => $this->faker->firstName, + 'last_name' => $this->faker->lastName, + 'is_individual' => 1 + ]); + + $data = [ + 'title' => $this->faker->words(15, true), + 'is_draft' => 0, + 'contents' => $this->faker->words($this->faker->numberBetween(50, 150), true), + 'author_Id' => $author->id, + ]; + $page = Page::create($data); + $this->assertNotNull($page->slug); + $newTitle = $this->faker->words(15, true); + $page->title = $newTitle; + $page->slug = null; + $page->save(); + $this->assertModelExists($page); + $this->assertDatabaseHas('pages', ['slug' => Str::slug($newTitle)]); + } } From f55cf57de71bba9357d189efeadb4bbfe73f23f4 Mon Sep 17 00:00:00 2001 From: Nick Rogers Date: Wed, 13 Mar 2024 02:12:22 +1030 Subject: [PATCH 3/3] fix: template routing for status badge --- src/Filament/Forms/Components/StatusBadge.php | 2 +- .../filament/forms/components}/status-badge.blade.php | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {resources/views/components/forms => views/filament/forms/components}/status-badge.blade.php (100%) diff --git a/src/Filament/Forms/Components/StatusBadge.php b/src/Filament/Forms/Components/StatusBadge.php index bb2eabb0..ae5a3567 100644 --- a/src/Filament/Forms/Components/StatusBadge.php +++ b/src/Filament/Forms/Components/StatusBadge.php @@ -11,5 +11,5 @@ class StatusBadge extends Field use HasBadge; use HasColor; - public const BADGE_VIEW = 'forms.components.status-badge'; + public const BADGE_VIEW = 'fila-cms::filament.forms.components.status-badge'; } diff --git a/resources/views/components/forms/status-badge.blade.php b/views/filament/forms/components/status-badge.blade.php similarity index 100% rename from resources/views/components/forms/status-badge.blade.php rename to views/filament/forms/components/status-badge.blade.php