fix: Nested infolist actions

This commit is contained in:
Dan Harrin
2023-09-10 23:53:53 +01:00
parent 2307297104
commit fdaf509626
18 changed files with 154 additions and 70 deletions
@@ -57,65 +57,6 @@
@endphp
@endif
@if ($this instanceof \Filament\Infolists\Contracts\HasInfolists && (! $this->hasInfolistsModalRendered))
<form wire:submit.prevent="callMountedInfolistAction">
@php
$action = $this->getMountedInfolistAction();
@endphp
<x-filament::modal
:alignment="$action?->getModalAlignment()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
:description="$action?->getModalDescription()"
display-classes="block"
:footer-actions="$action?->getVisibleModalFooterActions()"
:footer-actions-alignment="$action?->getModalFooterActionsAlignment()"
:heading="$action?->getModalHeading()"
:icon="$action?->getModalIcon()"
:icon-color="$action?->getModalIconColor()"
:id="$this->getId() . '-infolist-action'"
:slide-over="$action?->isModalSlideOver()"
:sticky-footer="$action?->isModalFooterSticky()"
:sticky-header="$action?->isModalHeaderSticky()"
:visible="filled($action)"
:width="$action?->getModalWidth()"
:wire:key="$action ? $this->getId() . '.infolist.actions.' . $action->getName() . '.modal' : null"
x-on:closed-form-component-action-modal.window="if (($event.detail.id === '{{ $this->getId() }}') && $wire.mountedInfolistActions.length) open()"
x-on:modal-closed.stop="
const mountedInfolistActionShouldOpenModal = {{ \Illuminate\Support\Js::from($action && $this->mountedInfolistActionShouldOpenModal()) }}
if (! mountedInfolistActionShouldOpenModal) {
return
}
if ($wire.mountedFormComponentActions.length) {
return
}
$wire.unmountInfolistAction(false)
"
x-on:opened-form-component-action-modal.window="if ($event.detail.id === '{{ $this->getId() }}') close()"
>
@if ($action)
{{ $action->getModalContent() }}
@if (count(($infolist = $action->getInfolist())?->getComponents() ?? []))
{{ $infolist }}
@elseif ($this->mountedInfolistActionHasForm())
{{ $this->getMountedInfolistActionForm() }}
@endif
{{ $action->getModalContentFooter() }}
@endif
</x-filament::modal>
</form>
@php
$this->hasInfolistsModalRendered = true;
@endphp
@endif
@if ($this instanceof \Filament\Tables\Contracts\HasTable && (! $this->hasTableModalRendered))
<form wire:submit.prevent="callMountedTableAction">
@php
@@ -228,6 +169,65 @@
@endphp
@endif
@if ($this instanceof \Filament\Infolists\Contracts\HasInfolists && (! $this->hasInfolistsModalRendered))
<form wire:submit.prevent="callMountedInfolistAction">
@php
$action = $this->getMountedInfolistAction();
@endphp
<x-filament::modal
:alignment="$action?->getModalAlignment()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
:description="$action?->getModalDescription()"
display-classes="block"
:footer-actions="$action?->getVisibleModalFooterActions()"
:footer-actions-alignment="$action?->getModalFooterActionsAlignment()"
:heading="$action?->getModalHeading()"
:icon="$action?->getModalIcon()"
:icon-color="$action?->getModalIconColor()"
:id="$this->getId() . '-infolist-action'"
:slide-over="$action?->isModalSlideOver()"
:sticky-footer="$action?->isModalFooterSticky()"
:sticky-header="$action?->isModalHeaderSticky()"
:visible="filled($action)"
:width="$action?->getModalWidth()"
:wire:key="$action ? $this->getId() . '.infolist.actions.' . $action->getName() . '.modal' : null"
x-on:closed-form-component-action-modal.window="if (($event.detail.id === '{{ $this->getId() }}') && $wire.mountedInfolistActions.length) open()"
x-on:modal-closed.stop="
const mountedInfolistActionShouldOpenModal = {{ \Illuminate\Support\Js::from($action && $this->mountedInfolistActionShouldOpenModal()) }}
if (! mountedInfolistActionShouldOpenModal) {
return
}
if ($wire.mountedFormComponentActions.length) {
return
}
$wire.unmountInfolistAction(false)
"
x-on:opened-form-component-action-modal.window="if ($event.detail.id === '{{ $this->getId() }}') close()"
>
@if ($action)
{{ $action->getModalContent() }}
@if (count(($infolist = $action->getInfolist())?->getComponents() ?? []))
{{ $infolist }}
@elseif ($this->mountedInfolistActionHasForm())
{{ $this->getMountedInfolistActionForm() }}
@endif
{{ $action->getModalContentFooter() }}
@endif
</x-filament::modal>
</form>
@php
$this->hasInfolistsModalRendered = true;
@endphp
@endif
@if (! $this->hasFormsModalRendered)
@php
$action = $this->getMountedFormComponentAction();
+5
View File
@@ -84,4 +84,9 @@ class Action extends MountableAction implements Contracts\Groupable, Contracts\H
$this->record(null);
}
public function getInfolistName(): string
{
return 'mountedActionInfolist';
}
}
+13 -1
View File
@@ -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;
}
}
@@ -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();
}
}
+1 -1
View File
@@ -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;
@@ -80,4 +80,9 @@ class Action extends MountableAction
default => parent::resolveDefaultClosureDependencyForEvaluationByType($parameterType),
};
}
public function getInfolistName(): string
{
return 'mountedFormComponentActionInfolist';
}
}
@@ -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();
}
}
@@ -2,6 +2,7 @@
namespace Filament\Infolists\Components\Actions;
use Exception;
use Filament\Actions\MountableAction;
use Filament\Actions\StaticAction;
use Illuminate\Database\Eloquent\Model;
@@ -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
+4 -1
View File
@@ -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';
@@ -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;
}
@@ -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
@@ -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;
}
+5
View File
@@ -110,4 +110,9 @@ class Action extends MountableAction implements Groupable, HasRecord, HasTable
->table($this->getTable())
->record($this->getRecord());
}
public function getInfolistName(): string
{
return 'mountedTableActionInfolist';
}
}
@@ -98,4 +98,9 @@ class BulkAction extends MountableAction implements Groupable, HasTable
return $arguments;
}
public function getInfolistName(): string
{
return 'mountedTableBulkActionInfolist';
}
}
@@ -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();
}
}
@@ -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();
}
}
+3 -1
View File
@@ -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;
}