From fdaf5096263194af2d77f44f5f3d86fe4a0506ff Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Sun, 10 Sep 2023 23:53:53 +0100 Subject: [PATCH] fix: Nested infolist actions --- .../views/components/modals.blade.php | 118 +++++++++--------- packages/actions/src/Action.php | 5 + packages/actions/src/Concerns/HasInfolist.php | 14 ++- .../src/Concerns/InteractsWithActions.php | 6 + packages/actions/src/MountableAction.php | 2 +- .../forms/src/Components/Actions/Action.php | 5 + .../forms/src/Concerns/InteractsWithForms.php | 6 + .../src/Components/Actions/Action.php | 1 + .../src/Concerns/InteractsWithInfolists.php | 26 +++- packages/panels/src/Pages/BasePage.php | 5 +- .../src/Resources/Pages/ListRecords.php | 3 +- .../panels/src/Resources/Pages/ViewRecord.php | 3 +- .../RelationManagers/RelationManager.php | 4 +- packages/tables/src/Actions/Action.php | 5 + packages/tables/src/Actions/BulkAction.php | 5 + packages/tables/src/Concerns/HasActions.php | 6 + .../tables/src/Concerns/HasBulkActions.php | 6 + packages/widgets/src/TableWidget.php | 4 +- 18 files changed, 154 insertions(+), 70 deletions(-) diff --git a/packages/actions/resources/views/components/modals.blade.php b/packages/actions/resources/views/components/modals.blade.php index 31ef15c415..02d257716d 100644 --- a/packages/actions/resources/views/components/modals.blade.php +++ b/packages/actions/resources/views/components/modals.blade.php @@ -57,65 +57,6 @@ @endphp @endif -@if ($this instanceof \Filament\Infolists\Contracts\HasInfolists && (! $this->hasInfolistsModalRendered)) -
- @php - $action = $this->getMountedInfolistAction(); - @endphp - - - @if ($action) - {{ $action->getModalContent() }} - - @if (count(($infolist = $action->getInfolist())?->getComponents() ?? [])) - {{ $infolist }} - @elseif ($this->mountedInfolistActionHasForm()) - {{ $this->getMountedInfolistActionForm() }} - @endif - - {{ $action->getModalContentFooter() }} - @endif - -
- - @php - $this->hasInfolistsModalRendered = true; - @endphp -@endif - @if ($this instanceof \Filament\Tables\Contracts\HasTable && (! $this->hasTableModalRendered))
@php @@ -228,6 +169,65 @@ @endphp @endif +@if ($this instanceof \Filament\Infolists\Contracts\HasInfolists && (! $this->hasInfolistsModalRendered)) + + @php + $action = $this->getMountedInfolistAction(); + @endphp + + + @if ($action) + {{ $action->getModalContent() }} + + @if (count(($infolist = $action->getInfolist())?->getComponents() ?? [])) + {{ $infolist }} + @elseif ($this->mountedInfolistActionHasForm()) + {{ $this->getMountedInfolistActionForm() }} + @endif + + {{ $action->getModalContentFooter() }} + @endif + +
+ + @php + $this->hasInfolistsModalRendered = true; + @endphp +@endif + @if (! $this->hasFormsModalRendered) @php $action = $this->getMountedFormComponentAction(); diff --git a/packages/actions/src/Action.php b/packages/actions/src/Action.php index 4d2be90999..af3fb942cb 100644 --- a/packages/actions/src/Action.php +++ b/packages/actions/src/Action.php @@ -84,4 +84,9 @@ class Action extends MountableAction implements Contracts\Groupable, Contracts\H $this->record(null); } + + public function getInfolistName(): string + { + return 'mountedActionInfolist'; + } } diff --git a/packages/actions/src/Concerns/HasInfolist.php b/packages/actions/src/Concerns/HasInfolist.php index b5d9ac769f..4f0e76bb73 100644 --- a/packages/actions/src/Concerns/HasInfolist.php +++ b/packages/actions/src/Concerns/HasInfolist.php @@ -26,7 +26,14 @@ trait HasInfolist public function getInfolist(): ?Infolist { - $infolist = Infolist::make($this->getLivewire()); + $infolistName = $this->getInfolistName(); + + if (blank($infolistName)) { + return null; + } + + $infolist = Infolist::make($this->getLivewire()) + ->name($infolistName); if ($this instanceof HasRecord) { $infolist->record($this->getRecord()); @@ -50,4 +57,9 @@ trait HasInfolist return $modifiedInfolist; } + + public function getInfolistName(): ?string + { + return null; + } } diff --git a/packages/actions/src/Concerns/InteractsWithActions.php b/packages/actions/src/Concerns/InteractsWithActions.php index 39f50afbd9..7872a7d73d 100644 --- a/packages/actions/src/Concerns/InteractsWithActions.php +++ b/packages/actions/src/Concerns/InteractsWithActions.php @@ -6,6 +6,7 @@ use Closure; use Filament\Actions\Action; use Filament\Forms; use Filament\Forms\Form; +use Filament\Infolists\Infolist; use Filament\Support\Exceptions\Cancel; use Filament\Support\Exceptions\Halt; use Illuminate\Database\Eloquent\Model; @@ -419,4 +420,9 @@ trait InteractsWithActions { return null; } + + public function mountedActionInfolist(): Infolist + { + return $this->getMountedAction()->getInfolist(); + } } diff --git a/packages/actions/src/MountableAction.php b/packages/actions/src/MountableAction.php index f1dace044f..60ef7929f2 100644 --- a/packages/actions/src/MountableAction.php +++ b/packages/actions/src/MountableAction.php @@ -7,7 +7,7 @@ use Filament\Notifications\Notification; use Filament\Support\Exceptions\Cancel; use Filament\Support\Exceptions\Halt; -class MountableAction extends StaticAction implements HasLivewire +abstract class MountableAction extends StaticAction implements HasLivewire { use Concerns\BelongsToLivewire; use Concerns\CanBeMounted; diff --git a/packages/forms/src/Components/Actions/Action.php b/packages/forms/src/Components/Actions/Action.php index 4f31cb0da2..9559440707 100644 --- a/packages/forms/src/Components/Actions/Action.php +++ b/packages/forms/src/Components/Actions/Action.php @@ -80,4 +80,9 @@ class Action extends MountableAction default => parent::resolveDefaultClosureDependencyForEvaluationByType($parameterType), }; } + + public function getInfolistName(): string + { + return 'mountedFormComponentActionInfolist'; + } } diff --git a/packages/forms/src/Concerns/InteractsWithForms.php b/packages/forms/src/Concerns/InteractsWithForms.php index a813227d1c..4400fdeff0 100644 --- a/packages/forms/src/Concerns/InteractsWithForms.php +++ b/packages/forms/src/Concerns/InteractsWithForms.php @@ -6,6 +6,7 @@ use Closure; use Exception; use Filament\Forms\Components\Component; use Filament\Forms\Form; +use Filament\Infolists\Infolist; use Filament\Support\Concerns\ResolvesDynamicLivewireProperties; use Filament\Support\Contracts\TranslatableContentDriver; use Illuminate\Database\Eloquent\Model; @@ -440,4 +441,9 @@ trait InteractsWithForms { return $this->isCachingForms; } + + public function mountedFormComponentActionInfolist(): Infolist + { + return $this->getMountedFormComponentAction()->getInfolist(); + } } diff --git a/packages/infolists/src/Components/Actions/Action.php b/packages/infolists/src/Components/Actions/Action.php index 27c3d5204b..d00081c515 100644 --- a/packages/infolists/src/Components/Actions/Action.php +++ b/packages/infolists/src/Components/Actions/Action.php @@ -2,6 +2,7 @@ namespace Filament\Infolists\Components\Actions; +use Exception; use Filament\Actions\MountableAction; use Filament\Actions\StaticAction; use Illuminate\Database\Eloquent\Model; diff --git a/packages/infolists/src/Concerns/InteractsWithInfolists.php b/packages/infolists/src/Concerns/InteractsWithInfolists.php index 0285408214..d9c64c4e18 100644 --- a/packages/infolists/src/Concerns/InteractsWithInfolists.php +++ b/packages/infolists/src/Concerns/InteractsWithInfolists.php @@ -2,7 +2,10 @@ namespace Filament\Infolists\Concerns; +use Exception; +use Filament\Actions\Contracts\HasActions; use Filament\Forms; +use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; use Filament\Infolists\Components\Actions\Action; use Filament\Infolists\Components\Component; @@ -10,6 +13,7 @@ use Filament\Infolists\Infolist; use Filament\Support\Exceptions\Cancel; use Filament\Support\Exceptions\Halt; +use Filament\Tables\Contracts\HasTable; use function Livewire\store; trait InteractsWithInfolists @@ -49,6 +53,10 @@ trait InteractsWithInfolists $infolist = $this->{$name}($this->makeInfolist()); + if (! ($infolist instanceof Infolist)) { + return null; + } + return $this->cacheInfolist($name, $infolist); } @@ -186,11 +194,25 @@ trait InteractsWithInfolists $this->resetErrorBag(); - $this->dispatch('open-modal', id: "{$this->getId()}-infolist-action"); + $this->openInfolistActionModal(); return null; } + protected function openInfolistActionModal(): void + { + if ( + ($this instanceof HasActions && count($this->mountedActions)) || + ($this instanceof HasForms && count($this->mountedFormComponentActions)) || + /** @phpstan-ignore-next-line */ + ($this instanceof HasTable && (count($this->mountedTableActions) || filled($this->mountedTableBulkAction))) + ) { + throw new Exception('Currently, infolist actions cannot open modals while they are nested within other action modals.'); + } + + $this->dispatch('open-modal', id: "{$this->getId()}-infolist-action"); + } + public function mountedInfolistActionShouldOpenModal(): bool { $action = $this->getMountedInfolistAction(); @@ -293,7 +315,7 @@ trait InteractsWithInfolists $this->resetErrorBag(); - $this->dispatch('open-modal', id: "{$this->getId()}-infolist-action"); + $this->openInfolistActionModal(); } protected function makeInfolist(): Infolist diff --git a/packages/panels/src/Pages/BasePage.php b/packages/panels/src/Pages/BasePage.php index 713afa9677..3fa1bc65d0 100644 --- a/packages/panels/src/Pages/BasePage.php +++ b/packages/panels/src/Pages/BasePage.php @@ -7,6 +7,8 @@ use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; +use Filament\Infolists\Concerns\InteractsWithInfolists; +use Filament\Infolists\Contracts\HasInfolists; use Filament\Support\Enums\Alignment; use Filament\Support\Exceptions\Halt; use Illuminate\Contracts\Support\Htmlable; @@ -14,10 +16,11 @@ use Illuminate\Contracts\View\View; use Illuminate\Validation\ValidationException; use Livewire\Component; -abstract class BasePage extends Component implements HasForms, HasActions +abstract class BasePage extends Component implements HasActions, HasForms, HasInfolists { use InteractsWithActions; use InteractsWithForms; + use InteractsWithInfolists; protected static string $layout = 'filament-panels::components.layout.base'; diff --git a/packages/panels/src/Resources/Pages/ListRecords.php b/packages/panels/src/Resources/Pages/ListRecords.php index 4e02a3e9a7..c544600972 100644 --- a/packages/panels/src/Resources/Pages/ListRecords.php +++ b/packages/panels/src/Resources/Pages/ListRecords.php @@ -19,9 +19,8 @@ use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Str; use Livewire\Attributes\Url; -class ListRecords extends Page implements Forms\Contracts\HasForms, Tables\Contracts\HasTable +class ListRecords extends Page implements Tables\Contracts\HasTable { - use Forms\Concerns\InteractsWithForms; use Tables\Concerns\InteractsWithTable { makeTable as makeBaseTable; } diff --git a/packages/panels/src/Resources/Pages/ViewRecord.php b/packages/panels/src/Resources/Pages/ViewRecord.php index 8fc29547d7..167d3267e0 100644 --- a/packages/panels/src/Resources/Pages/ViewRecord.php +++ b/packages/panels/src/Resources/Pages/ViewRecord.php @@ -19,12 +19,11 @@ use Illuminate\Database\Eloquent\Model; /** * @property Form $form */ -class ViewRecord extends Page implements HasInfolists +class ViewRecord extends Page { use Concerns\HasRelationManagers; use Concerns\InteractsWithRecord; use InteractsWithFormActions; - use InteractsWithInfolists; /** * @var view-string diff --git a/packages/panels/src/Resources/RelationManagers/RelationManager.php b/packages/panels/src/Resources/RelationManagers/RelationManager.php index e9d705924b..3389143352 100644 --- a/packages/panels/src/Resources/RelationManagers/RelationManager.php +++ b/packages/panels/src/Resources/RelationManagers/RelationManager.php @@ -5,6 +5,7 @@ namespace Filament\Resources\RelationManagers; use Filament\Actions; use Filament\Forms; use Filament\Forms\Form; +use Filament\Infolists; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; use Filament\Support\Enums\IconPosition; @@ -22,10 +23,11 @@ use Livewire\Component; use function Filament\authorize; -class RelationManager extends Component implements Actions\Contracts\HasActions, Forms\Contracts\HasForms, Tables\Contracts\HasTable +class RelationManager extends Component implements Actions\Contracts\HasActions, Infolists\Contracts\HasInfolists, Forms\Contracts\HasForms, Tables\Contracts\HasTable { use Actions\Concerns\InteractsWithActions; use Forms\Concerns\InteractsWithForms; + use Infolists\Concerns\InteractsWithInfolists; use Tables\Concerns\InteractsWithTable { makeTable as makeBaseTable; } diff --git a/packages/tables/src/Actions/Action.php b/packages/tables/src/Actions/Action.php index 975da56a80..9adfb7ff09 100644 --- a/packages/tables/src/Actions/Action.php +++ b/packages/tables/src/Actions/Action.php @@ -110,4 +110,9 @@ class Action extends MountableAction implements Groupable, HasRecord, HasTable ->table($this->getTable()) ->record($this->getRecord()); } + + public function getInfolistName(): string + { + return 'mountedTableActionInfolist'; + } } diff --git a/packages/tables/src/Actions/BulkAction.php b/packages/tables/src/Actions/BulkAction.php index 6fe5b51623..4a97529753 100644 --- a/packages/tables/src/Actions/BulkAction.php +++ b/packages/tables/src/Actions/BulkAction.php @@ -98,4 +98,9 @@ class BulkAction extends MountableAction implements Groupable, HasTable return $arguments; } + + public function getInfolistName(): string + { + return 'mountedTableBulkActionInfolist'; + } } diff --git a/packages/tables/src/Concerns/HasActions.php b/packages/tables/src/Concerns/HasActions.php index 5dbcfd1836..d852189457 100644 --- a/packages/tables/src/Concerns/HasActions.php +++ b/packages/tables/src/Concerns/HasActions.php @@ -3,6 +3,7 @@ namespace Filament\Tables\Concerns; use Filament\Forms\Form; +use Filament\Infolists\Infolist; use Filament\Support\Exceptions\Cancel; use Filament\Support\Exceptions\Halt; use Filament\Tables\Actions\Action; @@ -322,4 +323,9 @@ trait HasActions { return null; } + + public function mountedTableActionInfolist(): Infolist + { + return $this->getMountedTableAction()->getInfolist(); + } } diff --git a/packages/tables/src/Concerns/HasBulkActions.php b/packages/tables/src/Concerns/HasBulkActions.php index 75e7d0f921..8bbb8dfaa8 100644 --- a/packages/tables/src/Concerns/HasBulkActions.php +++ b/packages/tables/src/Concerns/HasBulkActions.php @@ -4,6 +4,7 @@ namespace Filament\Tables\Concerns; use Closure; use Filament\Forms\Form; +use Filament\Infolists\Infolist; use Filament\Support\Exceptions\Cancel; use Filament\Support\Exceptions\Halt; use Filament\Tables\Actions\BulkAction; @@ -404,4 +405,9 @@ trait HasBulkActions { return null; } + + public function mountedTableBulkActionInfolist(): Infolist + { + return $this->getMountedTableBulkAction()->getInfolist(); + } } diff --git a/packages/widgets/src/TableWidget.php b/packages/widgets/src/TableWidget.php index 23cdb91bde..55524bb382 100644 --- a/packages/widgets/src/TableWidget.php +++ b/packages/widgets/src/TableWidget.php @@ -4,16 +4,18 @@ namespace Filament\Widgets; use Filament\Actions; use Filament\Forms; +use Filament\Infolists; use Filament\Tables; use Filament\Tables\Table; use Illuminate\Contracts\Pagination\Paginator; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Builder; -class TableWidget extends Widget implements Actions\Contracts\HasActions, Forms\Contracts\HasForms, Tables\Contracts\HasTable +class TableWidget extends Widget implements Actions\Contracts\HasActions, Infolists\Contracts\HasInfolists, Forms\Contracts\HasForms, Tables\Contracts\HasTable { use Actions\Concerns\InteractsWithActions; use Forms\Concerns\InteractsWithForms; + use Infolists\Concerns\InteractsWithInfolists; use Tables\Concerns\InteractsWithTable { makeTable as makeBaseTable; }