mirror of
https://github.com/filamentphp/filament.git
synced 2026-10-24 12:04:06 +08:00
Remove the last of the action and actiongroup classes
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\User;
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Illuminate\Notifications\DatabaseNotification;
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -358,11 +358,11 @@ By default, there are two actions in the footer of a modal. The first is a butto
|
||||
To modify the action instance that is used to render one of the default action buttons, you may pass a closure to the `modalSubmitAction()` and `modalCancelAction()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Actions\StaticAction;
|
||||
use Filament\Actions\Action;
|
||||
|
||||
Action::make('help')
|
||||
->modalContent(view('actions.help'))
|
||||
->modalCancelAction(fn (StaticAction $action) => $action->label('Close'))
|
||||
->modalCancelAction(fn (Action $action) => $action->label('Close'))
|
||||
```
|
||||
|
||||
The [methods available to customize trigger buttons](trigger-button) will work to modify the `$action` instance inside the closure.
|
||||
|
||||
@@ -153,9 +153,7 @@ CreateAction::make()
|
||||
At any time, you may call `$action->halt()` from inside a lifecycle hook or mutation method, which will halt the entire creation process:
|
||||
|
||||
```php
|
||||
use App\Models\Post;
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use App\Models\Post;use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
CreateAction::make()
|
||||
->before(function (CreateAction $action, Post $record) {
|
||||
|
||||
@@ -166,7 +166,7 @@ EditAction::make()
|
||||
At any time, you may call `$action->halt()` from inside a lifecycle hook or mutation method, which will halt the entire saving process:
|
||||
|
||||
```php
|
||||
use App\Models\Post;use Filament\Actions\EditAction;use Filament\Notifications\Actions\Action;use Filament\Notifications\Notification;
|
||||
use App\Models\Post;use Filament\Actions\Action;use Filament\Actions\EditAction;use Filament\Notifications\Notification;
|
||||
|
||||
EditAction::make()
|
||||
->before(function (EditAction $action, Post $record) {
|
||||
|
||||
@@ -119,9 +119,7 @@ ReplicateAction::make()
|
||||
At any time, you may call `$action->halt()` from inside a lifecycle hook, which will halt the entire replication process:
|
||||
|
||||
```php
|
||||
use App\Models\Post;
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use App\Models\Post;use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
ReplicateAction::make()
|
||||
->before(function (ReplicateAction $action, Post $record) {
|
||||
|
||||
+317
-29
@@ -7,39 +7,105 @@ use Filament\Actions\Contracts\HasLivewire;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Schema\Components\Actions\ActionContainer;
|
||||
use Filament\Schema\Components\Actions\ActionContainer as InfolistActionContainer;
|
||||
use Filament\Support\Components\ViewComponent;
|
||||
use Filament\Support\Concerns\HasBadge;
|
||||
use Filament\Support\Concerns\HasColor;
|
||||
use Filament\Support\Concerns\HasExtraAttributes;
|
||||
use Filament\Support\Concerns\HasIcon;
|
||||
use Filament\Support\Exceptions\Cancel;
|
||||
use Filament\Support\Exceptions\Halt;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Js;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Action extends StaticAction implements Contracts\HasRecord, HasLivewire
|
||||
class Action extends ViewComponent implements Arrayable, Contracts\HasRecord, HasLivewire
|
||||
{
|
||||
use Concerns\BelongsToGroup;
|
||||
use Concerns\BelongsToLivewire;
|
||||
use Concerns\BelongsToSchemaComponent;
|
||||
use Concerns\BelongsToTable;
|
||||
use Concerns\CanAccessSelectedRecords;
|
||||
use Concerns\CanBeDisabled;
|
||||
use Concerns\CanBeHidden;
|
||||
use Concerns\CanBeLabeledFrom;
|
||||
use Concerns\CanBeMounted;
|
||||
use Concerns\CanBeOutlined;
|
||||
use Concerns\CanCallParentAction;
|
||||
use Concerns\CanClose;
|
||||
use Concerns\CanDeselectRecordsAfterCompletion;
|
||||
use Concerns\CanDispatchEvent;
|
||||
use Concerns\CanFetchSelectedRecords;
|
||||
use Concerns\CanNotify;
|
||||
use Concerns\CanOpenModal;
|
||||
use Concerns\CanOpenUrl;
|
||||
use Concerns\CanRedirect;
|
||||
use Concerns\CanRequireConfirmation;
|
||||
use Concerns\CanSubmitForm;
|
||||
use Concerns\CanSubmitForm;
|
||||
use Concerns\CanUseDatabaseTransactions;
|
||||
use Concerns\HasAction;
|
||||
use Concerns\HasArguments;
|
||||
use Concerns\HasForm;
|
||||
use Concerns\HasGroupedIcon;
|
||||
use Concerns\HasInfolist;
|
||||
use Concerns\HasKeyBindings;
|
||||
use Concerns\HasLabel;
|
||||
use Concerns\HasLifecycleHooks;
|
||||
use Concerns\HasMountableArguments;
|
||||
use Concerns\HasName;
|
||||
use Concerns\HasParentActions;
|
||||
use Concerns\HasSchema;
|
||||
use Concerns\HasSize;
|
||||
use Concerns\HasTooltip;
|
||||
use Concerns\HasWizard;
|
||||
use Concerns\InteractsWithRecord;
|
||||
use HasBadge;
|
||||
use HasColor;
|
||||
use HasExtraAttributes;
|
||||
use HasIcon;
|
||||
|
||||
protected bool | Closure $isBulk = false;
|
||||
|
||||
public const BADGE_VIEW = 'filament-actions::badge-action';
|
||||
|
||||
public const BUTTON_VIEW = 'filament-actions::button-action';
|
||||
|
||||
public const GROUPED_VIEW = 'filament-actions::grouped-action';
|
||||
|
||||
public const ICON_BUTTON_VIEW = 'filament-actions::icon-button-action';
|
||||
|
||||
public const LINK_VIEW = 'filament-actions::link-action';
|
||||
|
||||
protected string $evaluationIdentifier = 'action';
|
||||
|
||||
protected string $viewIdentifier = 'action';
|
||||
|
||||
protected ?string $livewireTarget = null;
|
||||
|
||||
protected string | Closure | null $alpineClickHandler = null;
|
||||
|
||||
protected bool | Closure $shouldMarkAsRead = false;
|
||||
|
||||
protected bool | Closure $shouldMarkAsUnread = false;
|
||||
|
||||
final public function __construct(?string $name)
|
||||
{
|
||||
$this->name($name);
|
||||
}
|
||||
|
||||
public static function make(?string $name = null): static
|
||||
{
|
||||
$static = app(static::class, [
|
||||
'name' => $name ?? static::getDefaultName(),
|
||||
]);
|
||||
$static->configure();
|
||||
|
||||
return $static;
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
@@ -50,9 +116,142 @@ class Action extends StaticAction implements Contracts\HasRecord, HasLivewire
|
||||
$this->successNotification(fn (Notification $notification): Notification => $notification);
|
||||
}
|
||||
|
||||
public function getLivewireCallMountedActionName(): string
|
||||
public function markAsRead(bool | Closure $condition = true): static
|
||||
{
|
||||
return 'callMountedAction';
|
||||
$this->shouldMarkAsRead = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function markAsUnread(bool | Closure $condition = true): static
|
||||
{
|
||||
$this->shouldMarkAsUnread = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->getName(),
|
||||
'color' => $this->getColor(),
|
||||
'event' => $this->getEvent(),
|
||||
'eventData' => $this->getEventData(),
|
||||
'dispatchDirection' => $this->getDispatchDirection(),
|
||||
'dispatchToComponent' => $this->getDispatchToComponent(),
|
||||
'extraAttributes' => $this->getExtraAttributes(),
|
||||
'icon' => $this->getIcon(),
|
||||
'iconPosition' => $this->getIconPosition(),
|
||||
'iconSize' => $this->getIconSize(),
|
||||
'isOutlined' => $this->isOutlined(),
|
||||
'isDisabled' => $this->isDisabled(),
|
||||
'label' => $this->getLabel(),
|
||||
'shouldClose' => $this->shouldClose(),
|
||||
'shouldMarkAsRead' => $this->shouldMarkAsRead(),
|
||||
'shouldMarkAsUnread' => $this->shouldMarkAsUnread(),
|
||||
'shouldOpenUrlInNewTab' => $this->shouldOpenUrlInNewTab(),
|
||||
'size' => $this->getSize(),
|
||||
'tooltip' => $this->getTooltip(),
|
||||
'url' => $this->getUrl(),
|
||||
'view' => $this->getView(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public static function fromArray(array $data): static
|
||||
{
|
||||
$static = static::make($data['name']);
|
||||
|
||||
$view = $data['view'] ?? null;
|
||||
|
||||
if (filled($view) && ($static->getView() !== $view) && static::isViewSafe($view)) {
|
||||
$static->view($view);
|
||||
}
|
||||
|
||||
if (filled($size = $data['size'] ?? null)) {
|
||||
$static->size($size);
|
||||
}
|
||||
|
||||
$static->close($data['shouldClose'] ?? false);
|
||||
$static->color($data['color'] ?? null);
|
||||
$static->disabled($data['isDisabled'] ?? false);
|
||||
|
||||
match ($data['dispatchDirection'] ?? null) {
|
||||
'self' => $static->dispatchSelf($data['event'] ?? null, $data['eventData'] ?? []),
|
||||
'to' => $static->dispatchTo($data['dispatchToComponent'] ?? null, $data['event'] ?? null, $data['eventData'] ?? []),
|
||||
default => $static->dispatch($data['event'] ?? null, $data['eventData'] ?? [])
|
||||
};
|
||||
|
||||
$static->extraAttributes($data['extraAttributes'] ?? []);
|
||||
$static->icon($data['icon'] ?? null);
|
||||
$static->iconPosition($data['iconPosition'] ?? null);
|
||||
$static->iconSize($data['iconSize'] ?? null);
|
||||
$static->label($data['label'] ?? null);
|
||||
$static->markAsRead($data['shouldMarkAsRead'] ?? false);
|
||||
$static->markAsUnread($data['shouldMarkAsUnread'] ?? false);
|
||||
$static->outlined($data['isOutlined'] ?? false);
|
||||
$static->url($data['url'] ?? null, $data['shouldOpenUrlInNewTab'] ?? false);
|
||||
$static->tooltip($data['tooltip'] ?? null);
|
||||
|
||||
return $static;
|
||||
}
|
||||
|
||||
public function isBadge(): bool
|
||||
{
|
||||
return $this->getView() === static::BADGE_VIEW;
|
||||
}
|
||||
|
||||
public function button(): static
|
||||
{
|
||||
return $this->view(static::BUTTON_VIEW);
|
||||
}
|
||||
|
||||
public function isButton(): bool
|
||||
{
|
||||
return $this->getView() === static::BUTTON_VIEW;
|
||||
}
|
||||
|
||||
public function grouped(): static
|
||||
{
|
||||
return $this->view(static::GROUPED_VIEW);
|
||||
}
|
||||
|
||||
public function iconButton(): static
|
||||
{
|
||||
return $this->view(static::ICON_BUTTON_VIEW);
|
||||
}
|
||||
|
||||
public function isIconButton(): bool
|
||||
{
|
||||
return $this->getView() === static::ICON_BUTTON_VIEW;
|
||||
}
|
||||
|
||||
public function link(): static
|
||||
{
|
||||
return $this->view(static::LINK_VIEW);
|
||||
}
|
||||
|
||||
public function isLink(): bool
|
||||
{
|
||||
return $this->getView() === static::LINK_VIEW;
|
||||
}
|
||||
|
||||
public function alpineClickHandler(string | Closure | null $handler): static
|
||||
{
|
||||
$this->alpineClickHandler = $handler;
|
||||
$this->livewireClickHandlerEnabled(blank($handler));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getLivewireClickHandler(): ?string
|
||||
@@ -69,6 +268,14 @@ class Action extends StaticAction implements Contracts\HasRecord, HasLivewire
|
||||
return $event;
|
||||
}
|
||||
|
||||
if (filled($handler = $this->getParentActionCallLivewireClickHandler())) {
|
||||
$handler .= '(';
|
||||
$handler .= Js::from($this->getArguments());
|
||||
$handler .= ')';
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
if ($this->canAccessSelectedRecords()) {
|
||||
return null;
|
||||
}
|
||||
@@ -76,6 +283,95 @@ class Action extends StaticAction implements Contracts\HasRecord, HasLivewire
|
||||
return $this->getJavaScriptClickHandler();
|
||||
}
|
||||
|
||||
public function getLivewireEventClickHandler(): ?string
|
||||
{
|
||||
$event = $this->getEvent();
|
||||
|
||||
if (blank($event)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$arguments = '';
|
||||
|
||||
if ($component = $this->getDispatchToComponent()) {
|
||||
$arguments .= Js::from($component)->toHtml();
|
||||
$arguments .= ', ';
|
||||
}
|
||||
|
||||
$arguments .= Js::from($event)->toHtml();
|
||||
|
||||
if ($this->getEventData()) {
|
||||
$arguments .= ', ';
|
||||
$arguments .= Js::from($this->getEventData())->toHtml();
|
||||
}
|
||||
|
||||
return match ($this->getDispatchDirection()) {
|
||||
'self' => "\$dispatchSelf($arguments)",
|
||||
'to' => "\$dispatchTo($arguments)",
|
||||
default => "\$dispatch($arguments)"
|
||||
};
|
||||
}
|
||||
|
||||
public function getAlpineClickHandler(): ?string
|
||||
{
|
||||
if (filled($handler = $this->evaluate($this->alpineClickHandler))) {
|
||||
return $handler;
|
||||
}
|
||||
|
||||
if ($this->shouldClose()) {
|
||||
return 'close()';
|
||||
}
|
||||
|
||||
if ($this->shouldMarkAsRead()) {
|
||||
return 'markAsRead()';
|
||||
}
|
||||
|
||||
if ($this->shouldMarkAsUnread()) {
|
||||
return 'markAsUnread()';
|
||||
}
|
||||
|
||||
if (! $this->canAccessSelectedRecords()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getJavaScriptClickHandler();
|
||||
}
|
||||
|
||||
public function livewireTarget(?string $target): static
|
||||
{
|
||||
$this->livewireTarget = $target;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLivewireTarget(): ?string
|
||||
{
|
||||
if (filled($this->livewireTarget)) {
|
||||
return $this->livewireTarget;
|
||||
}
|
||||
|
||||
if (! $this->canAccessSelectedRecords()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getJavaScriptClickHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `extraAttributes()` instead.
|
||||
*
|
||||
* @param array<mixed> $attributes
|
||||
*/
|
||||
public function withAttributes(array $attributes): static
|
||||
{
|
||||
return $this->extraAttributes($attributes);
|
||||
}
|
||||
|
||||
public function getLivewireCallMountedActionName(): string
|
||||
{
|
||||
return 'callMountedAction';
|
||||
}
|
||||
|
||||
protected function getJavaScriptClickHandler(): string
|
||||
{
|
||||
$argumentsParameter = '';
|
||||
@@ -119,32 +415,6 @@ class Action extends StaticAction implements Contracts\HasRecord, HasLivewire
|
||||
return "mountAction('{$this->getName()}'{$argumentsParameter}{$contextParameter})";
|
||||
}
|
||||
|
||||
public function getAlpineClickHandler(): ?string
|
||||
{
|
||||
if (filled($handler = parent::getAlpineClickHandler())) {
|
||||
return $handler;
|
||||
}
|
||||
|
||||
if (! $this->canAccessSelectedRecords()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getJavaScriptClickHandler();
|
||||
}
|
||||
|
||||
public function getLivewireTarget(): ?string
|
||||
{
|
||||
if (filled($target = parent::getLivewireTarget())) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
if (! $this->canAccessSelectedRecords()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getJavaScriptClickHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
@@ -270,4 +540,22 @@ class Action extends StaticAction implements Contracts\HasRecord, HasLivewire
|
||||
{
|
||||
return (bool) $this->evaluate($this->isBulk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param view-string $view
|
||||
*/
|
||||
protected static function isViewSafe(string $view): bool
|
||||
{
|
||||
return Str::startsWith($view, 'filament-actions::');
|
||||
}
|
||||
|
||||
public function shouldMarkAsRead(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->shouldMarkAsRead);
|
||||
}
|
||||
|
||||
public function shouldMarkAsUnread(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->shouldMarkAsUnread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,15 +12,16 @@ use Filament\Support\Concerns\HasColor;
|
||||
use Filament\Support\Concerns\HasExtraAttributes;
|
||||
use Filament\Support\Concerns\HasIcon;
|
||||
use Filament\Support\Facades\FilamentIcon;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Component;
|
||||
|
||||
class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
class ActionGroup extends ViewComponent implements Arrayable, HasLivewire, HasRecord
|
||||
{
|
||||
use Concerns\BelongsToGroup;
|
||||
use Concerns\BelongsToTable;
|
||||
use Concerns\CanBeHidden {
|
||||
isHidden as baseIsHidden;
|
||||
InteractsWithRecord::parseAuthorizationArguments insteadof Concerns\CanBeHidden;
|
||||
}
|
||||
use Concerns\CanBeLabeledFrom;
|
||||
use Concerns\CanBeOutlined;
|
||||
@@ -33,7 +34,7 @@ class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
use HasColor;
|
||||
use HasExtraAttributes;
|
||||
use HasIcon {
|
||||
getIcon as getBaseIcon;
|
||||
HasIcon::getIcon as getBaseIcon;
|
||||
}
|
||||
use InteractsWithRecord;
|
||||
|
||||
@@ -48,12 +49,12 @@ class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
public const LINK_VIEW = 'filament-actions::link-group';
|
||||
|
||||
/**
|
||||
* @var array<StaticAction | ActionGroup>
|
||||
* @var array<Action | ActionGroup>
|
||||
*/
|
||||
protected array $actions;
|
||||
|
||||
/**
|
||||
* @var array<string, StaticAction>
|
||||
* @var array<string, Action>
|
||||
*/
|
||||
protected array $flatActions;
|
||||
|
||||
@@ -64,7 +65,7 @@ class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
protected string $viewIdentifier = 'group';
|
||||
|
||||
/**
|
||||
* @param array<StaticAction | ActionGroup> $actions
|
||||
* @param array<Action | ActionGroup> $actions
|
||||
*/
|
||||
public function __construct(array $actions)
|
||||
{
|
||||
@@ -72,7 +73,7 @@ class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<StaticAction | ActionGroup> $actions
|
||||
* @param array<Action | ActionGroup> $actions
|
||||
*/
|
||||
public static function make(array $actions): static
|
||||
{
|
||||
@@ -90,7 +91,7 @@ class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<StaticAction | ActionGroup> $actions
|
||||
* @param array<Action | ActionGroup> $actions
|
||||
*/
|
||||
public function actions(array $actions): static
|
||||
{
|
||||
@@ -187,18 +188,18 @@ class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<StaticAction | ActionGroup>
|
||||
* @return array<Action | ActionGroup>
|
||||
*/
|
||||
public function getActions(): array
|
||||
{
|
||||
return array_map(
|
||||
fn (StaticAction | ActionGroup $action) => $action->defaultView($action::GROUPED_VIEW),
|
||||
fn (Action | ActionGroup $action) => $action->defaultView($action::GROUPED_VIEW),
|
||||
$this->actions,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, StaticAction>
|
||||
* @return array<string, Action>
|
||||
*/
|
||||
public function getFlatActions(): array
|
||||
{
|
||||
@@ -226,4 +227,79 @@ class ActionGroup extends ViewComponent implements HasLivewire, HasRecord
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'actions' => collect($this->getActions())->toArray(),
|
||||
'color' => $this->getColor(),
|
||||
'dropdownMaxHeight' => $this->getDropdownMaxHeight(),
|
||||
'dropdownOffset' => $this->getDropdownOffset(),
|
||||
'dropdownPlacement' => $this->getDropdownPlacement(),
|
||||
'dropdownWidth' => $this->getDropdownWidth(),
|
||||
'extraAttributes' => $this->getExtraAttributes(),
|
||||
'hasDropdown' => $this->hasDropdown(),
|
||||
'icon' => $this->getIcon(),
|
||||
'iconPosition' => $this->getIconPosition(),
|
||||
'iconSize' => $this->getIconSize(),
|
||||
'isOutlined' => $this->isOutlined(),
|
||||
'label' => $this->getLabel(),
|
||||
'size' => $this->getSize(),
|
||||
'tooltip' => $this->getTooltip(),
|
||||
'view' => $this->getView(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public static function fromArray(array $data): static
|
||||
{
|
||||
$static = static::make(
|
||||
array_map(
|
||||
fn (array $action): Action | \Filament\Actions\ActionGroup => match (array_key_exists('actions', $action)) {
|
||||
true => ActionGroup::fromArray($action),
|
||||
false => Action::fromArray($action),
|
||||
},
|
||||
$data['actions'] ?? [],
|
||||
),
|
||||
);
|
||||
|
||||
$view = $data['view'] ?? null;
|
||||
|
||||
if (filled($view) && ($static->getView() !== $view) && static::isViewSafe($view)) {
|
||||
$static->view($view);
|
||||
}
|
||||
|
||||
if (filled($size = $data['size'] ?? null)) {
|
||||
$static->size($size);
|
||||
}
|
||||
|
||||
$static->color($data['color'] ?? null);
|
||||
$static->dropdown($data['hasDropdown'] ?? false);
|
||||
$static->dropdownMaxHeight($data['dropdownMaxHeight'] ?? null);
|
||||
$static->dropdownOffset($data['dropdownOffset'] ?? null);
|
||||
$static->dropdownPlacement($data['dropdownPlacement'] ?? null);
|
||||
$static->dropdownWidth($data['dropdownWidth'] ?? null);
|
||||
$static->extraAttributes($data['extraAttributes'] ?? []);
|
||||
$static->icon($data['icon'] ?? null);
|
||||
$static->iconPosition($data['iconPosition'] ?? null);
|
||||
$static->iconSize($data['iconSize'] ?? null);
|
||||
$static->label($data['label'] ?? null);
|
||||
$static->outlined($data['isOutlined'] ?? null);
|
||||
$static->tooltip($data['tooltip'] ?? null);
|
||||
|
||||
return $static;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param view-string $view
|
||||
*/
|
||||
protected static function isViewSafe(string $view): bool
|
||||
{
|
||||
return Str::startsWith($view, 'filament-actions::');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,12 @@ trait CanBeHidden
|
||||
*/
|
||||
protected function parseAuthorizationArguments(array $arguments): array
|
||||
{
|
||||
if ($record = $this->getRecord()) {
|
||||
array_unshift($arguments, $record);
|
||||
} elseif ($model = $this->getModel()) {
|
||||
array_unshift($arguments, $model);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Filament\Actions\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\Action as NotificationAction;
|
||||
use Filament\Actions\Action as TableAction;
|
||||
use Filament\Actions\ImportAction;
|
||||
use Filament\Actions\ImportAction as ImportTableAction;
|
||||
@@ -13,7 +14,6 @@ use Filament\Actions\Imports\Jobs\ImportCsv;
|
||||
use Filament\Actions\Imports\Models\Import;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Notifications\Actions\Action as NotificationAction;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Schema\Components\Fieldset;
|
||||
use Filament\Schema\Components\Utilities\Get;
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Filament\Actions\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\StaticAction;
|
||||
use Filament\Support\Enums\Alignment;
|
||||
use Filament\Support\Enums\MaxWidth;
|
||||
use Filament\Support\View\Components\Modal;
|
||||
@@ -14,12 +13,12 @@ use Illuminate\Contracts\View\View;
|
||||
trait CanOpenModal
|
||||
{
|
||||
/**
|
||||
* @var array<string, StaticAction>
|
||||
* @var array<string, Action>
|
||||
*/
|
||||
protected array $cachedExtraModalFooterActions;
|
||||
|
||||
/**
|
||||
* @var array<StaticAction> | Closure
|
||||
* @var array<Action> | Closure
|
||||
*/
|
||||
protected array | Closure $extraModalFooterActions = [];
|
||||
|
||||
@@ -28,12 +27,12 @@ trait CanOpenModal
|
||||
protected bool | Closure | null $isModalHeaderSticky = null;
|
||||
|
||||
/**
|
||||
* @var array<string, StaticAction>
|
||||
* @var array<string, Action>
|
||||
*/
|
||||
protected array $cachedModalActions;
|
||||
|
||||
/**
|
||||
* @var array<StaticAction>
|
||||
* @var array<Action>
|
||||
*/
|
||||
protected array $modalActions = [];
|
||||
|
||||
@@ -42,22 +41,22 @@ trait CanOpenModal
|
||||
protected Alignment | string | Closure | null $modalAlignment = null;
|
||||
|
||||
/**
|
||||
* @var array<string, StaticAction>
|
||||
* @var array<string, Action>
|
||||
*/
|
||||
protected array $cachedModalFooterActions;
|
||||
|
||||
/**
|
||||
* @var array<StaticAction> | Closure | null
|
||||
* @var array<Action> | Closure | null
|
||||
*/
|
||||
protected array | Closure | null $modalFooterActions = null;
|
||||
|
||||
protected Alignment | string | Closure | null $modalFooterActionsAlignment = null;
|
||||
|
||||
protected StaticAction | bool | Closure | null $modalCancelAction = null;
|
||||
protected Action | bool | Closure | null $modalCancelAction = null;
|
||||
|
||||
protected string | Closure | null $modalCancelActionLabel = null;
|
||||
|
||||
protected StaticAction | bool | Closure | null $modalSubmitAction = null;
|
||||
protected Action | bool | Closure | null $modalSubmitAction = null;
|
||||
|
||||
protected string | Closure | null $modalSubmitActionLabel = null;
|
||||
|
||||
@@ -144,9 +143,9 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `modalFooterActions()` instead.
|
||||
* @param array<Action> | Closure | null $actions
|
||||
*
|
||||
* @param array<StaticAction> | Closure | null $actions
|
||||
*@deprecated Use `modalFooterActions()` instead.
|
||||
*/
|
||||
public function modalActions(array | Closure | null $actions = null): static
|
||||
{
|
||||
@@ -156,7 +155,7 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<StaticAction> | Closure | null $actions
|
||||
* @param array<Action> | Closure | null $actions
|
||||
*/
|
||||
public function modalFooterActions(array | Closure | null $actions = null): static
|
||||
{
|
||||
@@ -173,9 +172,9 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `extraModalFooterActions()` instead.
|
||||
* @param array<Action> | Closure $actions
|
||||
*
|
||||
* @param array<StaticAction> | Closure $actions
|
||||
*@deprecated Use `extraModalFooterActions()` instead.
|
||||
*/
|
||||
public function extraModalActions(array | Closure $actions): static
|
||||
{
|
||||
@@ -185,7 +184,7 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<StaticAction> | Closure $actions
|
||||
* @param array<Action> | Closure $actions
|
||||
*/
|
||||
public function extraModalFooterActions(array | Closure $actions): static
|
||||
{
|
||||
@@ -195,7 +194,7 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<StaticAction> $actions
|
||||
* @param array<Action> $actions
|
||||
*/
|
||||
public function registerModalActions(array $actions): static
|
||||
{
|
||||
@@ -207,14 +206,14 @@ trait CanOpenModal
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function modalSubmitAction(StaticAction | bool | Closure | null $action = null): static
|
||||
public function modalSubmitAction(Action | bool | Closure | null $action = null): static
|
||||
{
|
||||
$this->modalSubmitAction = $action;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function modalCancelAction(StaticAction | bool | Closure | null $action = null): static
|
||||
public function modalCancelAction(Action | bool | Closure | null $action = null): static
|
||||
{
|
||||
$this->modalCancelAction = $action;
|
||||
|
||||
@@ -318,7 +317,7 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, StaticAction>
|
||||
* @return array<string, Action>
|
||||
*/
|
||||
public function getModalFooterActions(): array
|
||||
{
|
||||
@@ -368,7 +367,7 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, StaticAction>
|
||||
* @return array<string, Action>
|
||||
*/
|
||||
public function getModalActions(): array
|
||||
{
|
||||
@@ -385,7 +384,7 @@ trait CanOpenModal
|
||||
return $this->cachedModalActions = $actions;
|
||||
}
|
||||
|
||||
public function getModalAction(string $name): ?StaticAction
|
||||
public function getModalAction(string $name): ?Action
|
||||
{
|
||||
return $this->getModalActions()[$name] ?? null;
|
||||
}
|
||||
@@ -401,7 +400,7 @@ trait CanOpenModal
|
||||
return $action;
|
||||
}
|
||||
|
||||
public function prepareModalAction(StaticAction $action): StaticAction
|
||||
public function prepareModalAction(Action $action): Action
|
||||
{
|
||||
if (! $action instanceof Action) {
|
||||
return $action;
|
||||
@@ -415,17 +414,17 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<StaticAction>
|
||||
* @return array<Action>
|
||||
*/
|
||||
public function getVisibleModalFooterActions(): array
|
||||
{
|
||||
return array_filter(
|
||||
$this->getModalFooterActions(),
|
||||
fn (StaticAction $action): bool => $action->isVisible(),
|
||||
fn (Action $action): bool => $action->isVisible(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getModalSubmitAction(): ?StaticAction
|
||||
public function getModalSubmitAction(): ?Action
|
||||
{
|
||||
$action = static::makeModalAction('submit')
|
||||
->label($this->getModalSubmitActionLabel())
|
||||
@@ -446,7 +445,7 @@ trait CanOpenModal
|
||||
return $action;
|
||||
}
|
||||
|
||||
public function getModalCancelAction(): ?StaticAction
|
||||
public function getModalCancelAction(): ?Action
|
||||
{
|
||||
$action = static::makeModalAction('cancel')
|
||||
->label($this->getModalCancelActionLabel())
|
||||
@@ -465,7 +464,7 @@ trait CanOpenModal
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<StaticAction>
|
||||
* @return array<Action>
|
||||
*/
|
||||
public function getExtraModalFooterActions(): array
|
||||
{
|
||||
@@ -594,7 +593,7 @@ trait CanOpenModal
|
||||
*
|
||||
* @param array<string, mixed> | null $arguments
|
||||
*/
|
||||
public function makeExtraModalAction(string $name, ?array $arguments = null): StaticAction
|
||||
public function makeExtraModalAction(string $name, ?array $arguments = null): Action
|
||||
{
|
||||
return $this->makeModalSubmitAction($name, $arguments);
|
||||
}
|
||||
@@ -602,7 +601,7 @@ trait CanOpenModal
|
||||
/**
|
||||
* @param array<string, mixed> | null $arguments
|
||||
*/
|
||||
public function makeModalSubmitAction(string $name, ?array $arguments = null): StaticAction
|
||||
public function makeModalSubmitAction(string $name, ?array $arguments = null): Action
|
||||
{
|
||||
return static::makeModalAction($name)
|
||||
->callParent($this->getLivewireCallMountedActionName())
|
||||
@@ -610,9 +609,9 @@ trait CanOpenModal
|
||||
->color('gray');
|
||||
}
|
||||
|
||||
public function makeModalAction(string $name): StaticAction
|
||||
public function makeModalAction(string $name): Action
|
||||
{
|
||||
return StaticAction::make($name)
|
||||
return Action::make($name)
|
||||
->button();
|
||||
}
|
||||
|
||||
|
||||
@@ -263,21 +263,6 @@ trait InteractsWithRecord
|
||||
return $this->evaluate($this->pluralModelLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $arguments
|
||||
* @return array<mixed>
|
||||
*/
|
||||
protected function parseAuthorizationArguments(array $arguments): array
|
||||
{
|
||||
if ($record = $this->getRecord()) {
|
||||
array_unshift($arguments, $record);
|
||||
} elseif ($model = $this->getModel()) {
|
||||
array_unshift($arguments, $model);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
public function getRecords(): EloquentCollection | Collection | null
|
||||
{
|
||||
return $this->records = $this->evaluate($this->records);
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace Filament\Actions\Exports\Enums;
|
||||
|
||||
use Filament\Actions\Action as NotificationAction;
|
||||
use Filament\Actions\Exports\Downloaders\Contracts\Downloader;
|
||||
use Filament\Actions\Exports\Downloaders\CsvDownloader;
|
||||
use Filament\Actions\Exports\Downloaders\XlsxDownloader;
|
||||
use Filament\Actions\Exports\Models\Export;
|
||||
use Filament\Notifications\Actions\Action as NotificationAction;
|
||||
|
||||
enum ExportFormat: string
|
||||
{
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace Filament\Actions\Exports\Jobs;
|
||||
|
||||
use Filament\Actions\Action as NotificationAction;
|
||||
use Filament\Actions\Exports\Enums\ExportFormat;
|
||||
use Filament\Actions\Exports\Exporter;
|
||||
use Filament\Actions\Exports\Models\Export;
|
||||
use Filament\Notifications\Actions\Action as NotificationAction;
|
||||
use Filament\Notifications\Notification;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Actions;
|
||||
|
||||
use Closure;
|
||||
use Filament\Support\Components\ViewComponent;
|
||||
use Filament\Support\Concerns\HasBadge;
|
||||
use Filament\Support\Concerns\HasColor;
|
||||
use Filament\Support\Concerns\HasExtraAttributes;
|
||||
use Filament\Support\Concerns\HasIcon;
|
||||
use Illuminate\Support\Js;
|
||||
use Illuminate\Support\Traits\Conditionable;
|
||||
|
||||
class StaticAction extends ViewComponent
|
||||
{
|
||||
use Concerns\BelongsToGroup;
|
||||
use Concerns\CanBeDisabled;
|
||||
use Concerns\CanBeHidden;
|
||||
use Concerns\CanBeLabeledFrom;
|
||||
use Concerns\CanBeOutlined;
|
||||
use Concerns\CanCallParentAction;
|
||||
use Concerns\CanClose;
|
||||
use Concerns\CanDispatchEvent;
|
||||
use Concerns\CanOpenUrl;
|
||||
use Concerns\CanSubmitForm;
|
||||
use Concerns\HasAction;
|
||||
use Concerns\HasArguments;
|
||||
use Concerns\HasGroupedIcon;
|
||||
use Concerns\HasKeyBindings;
|
||||
use Concerns\HasLabel;
|
||||
use Concerns\HasName;
|
||||
use Concerns\HasSize;
|
||||
use Concerns\HasTooltip;
|
||||
use Conditionable;
|
||||
use HasBadge;
|
||||
use HasColor;
|
||||
use HasExtraAttributes;
|
||||
use HasIcon;
|
||||
|
||||
public const BADGE_VIEW = 'filament-actions::badge-action';
|
||||
|
||||
public const BUTTON_VIEW = 'filament-actions::button-action';
|
||||
|
||||
public const GROUPED_VIEW = 'filament-actions::grouped-action';
|
||||
|
||||
public const ICON_BUTTON_VIEW = 'filament-actions::icon-button-action';
|
||||
|
||||
public const LINK_VIEW = 'filament-actions::link-action';
|
||||
|
||||
protected string $evaluationIdentifier = 'action';
|
||||
|
||||
protected string $viewIdentifier = 'action';
|
||||
|
||||
protected ?string $livewireTarget = null;
|
||||
|
||||
protected string | Closure | null $alpineClickHandler = null;
|
||||
|
||||
final public function __construct(?string $name)
|
||||
{
|
||||
$this->name($name);
|
||||
}
|
||||
|
||||
public static function make(?string $name = null): static
|
||||
{
|
||||
$static = app(static::class, [
|
||||
'name' => $name ?? static::getDefaultName(),
|
||||
]);
|
||||
$static->configure();
|
||||
|
||||
return $static;
|
||||
}
|
||||
|
||||
public function isBadge(): bool
|
||||
{
|
||||
return $this->getView() === static::BADGE_VIEW;
|
||||
}
|
||||
|
||||
public function button(): static
|
||||
{
|
||||
return $this->view(static::BUTTON_VIEW);
|
||||
}
|
||||
|
||||
public function isButton(): bool
|
||||
{
|
||||
return $this->getView() === static::BUTTON_VIEW;
|
||||
}
|
||||
|
||||
public function grouped(): static
|
||||
{
|
||||
return $this->view(static::GROUPED_VIEW);
|
||||
}
|
||||
|
||||
public function iconButton(): static
|
||||
{
|
||||
return $this->view(static::ICON_BUTTON_VIEW);
|
||||
}
|
||||
|
||||
public function isIconButton(): bool
|
||||
{
|
||||
return $this->getView() === static::ICON_BUTTON_VIEW;
|
||||
}
|
||||
|
||||
public function link(): static
|
||||
{
|
||||
return $this->view(static::LINK_VIEW);
|
||||
}
|
||||
|
||||
public function isLink(): bool
|
||||
{
|
||||
return $this->getView() === static::LINK_VIEW;
|
||||
}
|
||||
|
||||
public function alpineClickHandler(string | Closure | null $handler): static
|
||||
{
|
||||
$this->alpineClickHandler = $handler;
|
||||
$this->livewireClickHandlerEnabled(blank($handler));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getLivewireClickHandler(): ?string
|
||||
{
|
||||
if (! $this->isLivewireClickHandlerEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_string($this->action)) {
|
||||
return $this->action;
|
||||
}
|
||||
|
||||
if ($event = $this->getLivewireEventClickHandler()) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
if ($handler = $this->getParentActionCallLivewireClickHandler()) {
|
||||
$handler .= '(';
|
||||
$handler .= Js::from($this->getArguments());
|
||||
$handler .= ')';
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getLivewireEventClickHandler(): ?string
|
||||
{
|
||||
$event = $this->getEvent();
|
||||
|
||||
if (blank($event)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$arguments = '';
|
||||
|
||||
if ($component = $this->getDispatchToComponent()) {
|
||||
$arguments .= Js::from($component)->toHtml();
|
||||
$arguments .= ', ';
|
||||
}
|
||||
|
||||
$arguments .= Js::from($event)->toHtml();
|
||||
|
||||
if ($this->getEventData()) {
|
||||
$arguments .= ', ';
|
||||
$arguments .= Js::from($this->getEventData())->toHtml();
|
||||
}
|
||||
|
||||
return match ($this->getDispatchDirection()) {
|
||||
'self' => "\$dispatchSelf($arguments)",
|
||||
'to' => "\$dispatchTo($arguments)",
|
||||
default => "\$dispatch($arguments)"
|
||||
};
|
||||
}
|
||||
|
||||
public function getAlpineClickHandler(): ?string
|
||||
{
|
||||
if (filled($handler = $this->evaluate($this->alpineClickHandler))) {
|
||||
return $handler;
|
||||
}
|
||||
|
||||
if (! $this->shouldClose()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return 'close()';
|
||||
}
|
||||
|
||||
public function livewireTarget(?string $target): static
|
||||
{
|
||||
$this->livewireTarget = $target;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLivewireTarget(): ?string
|
||||
{
|
||||
return $this->livewireTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `extraAttributes()` instead.
|
||||
*
|
||||
* @param array<mixed> $attributes
|
||||
*/
|
||||
public function withAttributes(array $attributes): static
|
||||
{
|
||||
return $this->extraAttributes($attributes);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ use Filament\Actions\Action;
|
||||
use Filament\Actions\ActionGroup;
|
||||
use Filament\Actions\Contracts\HasActions;
|
||||
use Filament\Actions\Exceptions\ActionNotResolvableException;
|
||||
use Filament\Actions\StaticAction;
|
||||
use Filament\Actions\Testing\Fixtures\TestAction;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
@@ -550,7 +549,7 @@ class TestsActions
|
||||
|
||||
$actions = array_reduce(
|
||||
$actions,
|
||||
function (array $carry, StaticAction | ActionGroup $action): array {
|
||||
function (array $carry, Action | ActionGroup $action): array {
|
||||
if ($action instanceof ActionGroup) {
|
||||
return [
|
||||
...$carry,
|
||||
|
||||
@@ -26,7 +26,7 @@ class ViewAction extends Action
|
||||
$this->modalHeading(fn (): string => __('filament-actions::view.single.modal.heading', ['label' => $this->getRecordTitle()]));
|
||||
|
||||
$this->modalSubmitAction(false);
|
||||
$this->modalCancelAction(fn (StaticAction $action) => $action->label(__('filament-actions::view.single.modal.actions.close.label')));
|
||||
$this->modalCancelAction(fn (Action $action) => $action->label(__('filament-actions::view.single.modal.actions.close.label')));
|
||||
|
||||
$this->color('gray');
|
||||
|
||||
|
||||
@@ -224,8 +224,7 @@ new FilamentNotification()
|
||||
Notifications support [Actions](../actions/trigger-button), which are buttons that render below the content of the notification. They can open a URL or dispatch a Livewire event. Actions can be defined as follows:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
Notification::make()
|
||||
->title('Saved successfully')
|
||||
@@ -265,8 +264,7 @@ You can learn more about how to style action buttons [here](../actions/trigger-b
|
||||
You can open a URL, optionally in a new tab, when clicking on an action:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
Notification::make()
|
||||
->title('Saved successfully')
|
||||
@@ -305,8 +303,7 @@ new FilamentNotification()
|
||||
Sometimes you want to execute additional code when a notification action is clicked. This can be achieved by setting a Livewire event which should be dispatched on clicking the action. You may optionally pass an array of data, which will be available as parameters in the event listener on your Livewire component:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
Notification::make()
|
||||
->title('Saved successfully')
|
||||
@@ -371,8 +368,7 @@ new FilamentNotificationAction('undo')
|
||||
After opening a URL or dispatching an event from your action, you may want to close the notification right away:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
Notification::make()
|
||||
->title('Saved successfully')
|
||||
|
||||
@@ -141,8 +141,7 @@ event(new DatabaseNotificationsSent($recipient));
|
||||
There is a button at the top of the modal to mark all notifications as read at once. You may also add [Actions](sending-notifications#adding-actions-to-notifications) to notifications, which you can use to mark individual notifications as read. To do this, use the `markAsRead()` method on the action:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
Notification::make()
|
||||
->title('Saved successfully')
|
||||
@@ -159,8 +158,7 @@ Notification::make()
|
||||
Alternatively, you may use the `markAsUnread()` method to mark a notification as unread:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
Notification::make()
|
||||
->title('Saved successfully')
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Notifications\Actions;
|
||||
|
||||
use Closure;
|
||||
use Filament\Actions\StaticAction;
|
||||
use Filament\Support\Enums\ActionSize;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Action extends StaticAction implements Arrayable
|
||||
{
|
||||
protected string $viewIdentifier = 'action';
|
||||
|
||||
protected bool | Closure $shouldMarkAsRead = false;
|
||||
|
||||
protected bool | Closure $shouldMarkAsUnread = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->defaultView(static::LINK_VIEW);
|
||||
|
||||
$this->defaultSize(ActionSize::Small);
|
||||
}
|
||||
|
||||
public function markAsRead(bool | Closure $condition = true): static
|
||||
{
|
||||
$this->shouldMarkAsRead = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function markAsUnread(bool | Closure $condition = true): static
|
||||
{
|
||||
$this->shouldMarkAsUnread = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->getName(),
|
||||
'color' => $this->getColor(),
|
||||
'event' => $this->getEvent(),
|
||||
'eventData' => $this->getEventData(),
|
||||
'dispatchDirection' => $this->getDispatchDirection(),
|
||||
'dispatchToComponent' => $this->getDispatchToComponent(),
|
||||
'extraAttributes' => $this->getExtraAttributes(),
|
||||
'icon' => $this->getIcon(),
|
||||
'iconPosition' => $this->getIconPosition(),
|
||||
'iconSize' => $this->getIconSize(),
|
||||
'isOutlined' => $this->isOutlined(),
|
||||
'isDisabled' => $this->isDisabled(),
|
||||
'label' => $this->getLabel(),
|
||||
'shouldClose' => $this->shouldClose(),
|
||||
'shouldMarkAsRead' => $this->shouldMarkAsRead(),
|
||||
'shouldMarkAsUnread' => $this->shouldMarkAsUnread(),
|
||||
'shouldOpenUrlInNewTab' => $this->shouldOpenUrlInNewTab(),
|
||||
'size' => $this->getSize(),
|
||||
'tooltip' => $this->getTooltip(),
|
||||
'url' => $this->getUrl(),
|
||||
'view' => $this->getView(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public static function fromArray(array $data): static
|
||||
{
|
||||
$static = static::make($data['name']);
|
||||
|
||||
$view = $data['view'] ?? null;
|
||||
|
||||
if (filled($view) && ($static->getView() !== $view) && static::isViewSafe($view)) {
|
||||
$static->view($view);
|
||||
}
|
||||
|
||||
if (filled($size = $data['size'] ?? null)) {
|
||||
$static->size($size);
|
||||
}
|
||||
|
||||
$static->close($data['shouldClose'] ?? false);
|
||||
$static->color($data['color'] ?? null);
|
||||
$static->disabled($data['isDisabled'] ?? false);
|
||||
|
||||
match ($data['dispatchDirection'] ?? null) {
|
||||
'self' => $static->dispatchSelf($data['event'] ?? null, $data['eventData'] ?? []),
|
||||
'to' => $static->dispatchTo($data['dispatchToComponent'] ?? null, $data['event'] ?? null, $data['eventData'] ?? []),
|
||||
default => $static->dispatch($data['event'] ?? null, $data['eventData'] ?? [])
|
||||
};
|
||||
|
||||
$static->extraAttributes($data['extraAttributes'] ?? []);
|
||||
$static->icon($data['icon'] ?? null);
|
||||
$static->iconPosition($data['iconPosition'] ?? null);
|
||||
$static->iconSize($data['iconSize'] ?? null);
|
||||
$static->label($data['label'] ?? null);
|
||||
$static->markAsRead($data['shouldMarkAsRead'] ?? false);
|
||||
$static->markAsUnread($data['shouldMarkAsUnread'] ?? false);
|
||||
$static->outlined($data['isOutlined'] ?? false);
|
||||
$static->url($data['url'] ?? null, $data['shouldOpenUrlInNewTab'] ?? false);
|
||||
$static->tooltip($data['tooltip'] ?? null);
|
||||
|
||||
return $static;
|
||||
}
|
||||
|
||||
public function getAlpineClickHandler(): ?string
|
||||
{
|
||||
if (filled($handler = parent::getAlpineClickHandler())) {
|
||||
return $handler;
|
||||
}
|
||||
|
||||
if ($this->shouldMarkAsRead()) {
|
||||
return 'markAsRead()';
|
||||
}
|
||||
|
||||
if ($this->shouldMarkAsUnread()) {
|
||||
return 'markAsUnread()';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param view-string $view
|
||||
*/
|
||||
protected static function isViewSafe(string $view): bool
|
||||
{
|
||||
return Str::startsWith($view, 'filament-actions::');
|
||||
}
|
||||
|
||||
public function shouldMarkAsRead(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->shouldMarkAsRead);
|
||||
}
|
||||
|
||||
public function shouldMarkAsUnread(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->shouldMarkAsUnread);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Notifications\Actions;
|
||||
|
||||
use Filament\Actions\ActionGroup as BaseActionGroup;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property array<Action> $actions
|
||||
*/
|
||||
class ActionGroup extends BaseActionGroup implements Arrayable
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'actions' => collect($this->getActions())->toArray(),
|
||||
'color' => $this->getColor(),
|
||||
'dropdownMaxHeight' => $this->getDropdownMaxHeight(),
|
||||
'dropdownOffset' => $this->getDropdownOffset(),
|
||||
'dropdownPlacement' => $this->getDropdownPlacement(),
|
||||
'dropdownWidth' => $this->getDropdownWidth(),
|
||||
'extraAttributes' => $this->getExtraAttributes(),
|
||||
'hasDropdown' => $this->hasDropdown(),
|
||||
'icon' => $this->getIcon(),
|
||||
'iconPosition' => $this->getIconPosition(),
|
||||
'iconSize' => $this->getIconSize(),
|
||||
'isOutlined' => $this->isOutlined(),
|
||||
'label' => $this->getLabel(),
|
||||
'size' => $this->getSize(),
|
||||
'tooltip' => $this->getTooltip(),
|
||||
'view' => $this->getView(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public static function fromArray(array $data): static
|
||||
{
|
||||
$static = static::make(
|
||||
array_map(
|
||||
fn (array $action): Action | ActionGroup => match (array_key_exists('actions', $action)) {
|
||||
true => ActionGroup::fromArray($action),
|
||||
false => Action::fromArray($action),
|
||||
},
|
||||
$data['actions'] ?? [],
|
||||
),
|
||||
);
|
||||
|
||||
$view = $data['view'] ?? null;
|
||||
|
||||
if (filled($view) && ($static->getView() !== $view) && static::isViewSafe($view)) {
|
||||
$static->view($view);
|
||||
}
|
||||
|
||||
if (filled($size = $data['size'] ?? null)) {
|
||||
$static->size($size);
|
||||
}
|
||||
|
||||
$static->color($data['color'] ?? null);
|
||||
$static->dropdown($data['hasDropdown'] ?? false);
|
||||
$static->dropdownMaxHeight($data['dropdownMaxHeight'] ?? null);
|
||||
$static->dropdownOffset($data['dropdownOffset'] ?? null);
|
||||
$static->dropdownPlacement($data['dropdownPlacement'] ?? null);
|
||||
$static->dropdownWidth($data['dropdownWidth'] ?? null);
|
||||
$static->extraAttributes($data['extraAttributes'] ?? []);
|
||||
$static->icon($data['icon'] ?? null);
|
||||
$static->iconPosition($data['iconPosition'] ?? null);
|
||||
$static->iconSize($data['iconSize'] ?? null);
|
||||
$static->label($data['label'] ?? null);
|
||||
$static->outlined($data['isOutlined'] ?? null);
|
||||
$static->tooltip($data['tooltip'] ?? null);
|
||||
|
||||
return $static;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param view-string $view
|
||||
*/
|
||||
protected static function isViewSafe(string $view): bool
|
||||
{
|
||||
return Str::startsWith($view, 'filament-actions::');
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,9 @@
|
||||
namespace Filament\Notifications\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Actions\ActionGroup;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\ActionGroup;
|
||||
use Filament\Support\Enums\ActionSize;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait HasActions
|
||||
@@ -29,6 +30,11 @@ trait HasActions
|
||||
*/
|
||||
public function getActions(): array
|
||||
{
|
||||
return Arr::wrap($this->evaluate($this->actions));
|
||||
return array_map(
|
||||
fn (Action $action) => $action
|
||||
->defaultView(\Filament\Actions\Action::LINK_VIEW)
|
||||
->defaultSize(ActionSize::Small),
|
||||
Arr::wrap($this->evaluate($this->actions)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Filament\Notifications;
|
||||
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Actions\ActionGroup;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\ActionGroup;
|
||||
use Filament\Notifications\Events\DatabaseNotificationsSent;
|
||||
use Filament\Notifications\Livewire\Notifications;
|
||||
use Filament\Support\Components\ViewComponent;
|
||||
|
||||
@@ -157,8 +157,7 @@ Alternatively, if you're creating records in a modal action, check out the [Acti
|
||||
At any time, you may call `$this->halt()` from inside a lifecycle hook or mutation method, which will halt the entire creation process:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
protected function beforeCreate(): void
|
||||
{
|
||||
|
||||
@@ -211,8 +211,7 @@ The `$operation` helper is available, to ensure that the action is only visible
|
||||
At any time, you may call `$this->halt()` from inside a lifecycle hook or mutation method, which will halt the entire saving process:
|
||||
|
||||
```php
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Actions\Action;use Filament\Notifications\Notification;
|
||||
|
||||
protected function beforeSave(): void
|
||||
{
|
||||
|
||||
@@ -81,7 +81,7 @@ Global search supports actions, which are buttons that render below each search
|
||||
Actions can be defined as follows:
|
||||
|
||||
```php
|
||||
use Filament\GlobalSearch\Actions\Action;
|
||||
use Filament\Actions\Action;
|
||||
|
||||
public static function getGlobalSearchResultActions(Model $record): array
|
||||
{
|
||||
@@ -99,7 +99,7 @@ You can learn more about how to style action buttons [here](../../actions/trigge
|
||||
You can open a URL, optionally in a new tab, when clicking on an action:
|
||||
|
||||
```php
|
||||
use Filament\GlobalSearch\Actions\Action;
|
||||
use Filament\Actions\Action;
|
||||
|
||||
Action::make('view')
|
||||
->url(static::getUrl('view', ['record' => $record]), shouldOpenInNewTab: true)
|
||||
@@ -110,7 +110,7 @@ Action::make('view')
|
||||
Sometimes you want to execute additional code when a global search result action is clicked. This can be achieved by setting a Livewire event which should be dispatched on clicking the action. You may optionally pass an array of data, which will be available as parameters in the event listener on your Livewire component:
|
||||
|
||||
```php
|
||||
use Filament\GlobalSearch\Actions\Action;
|
||||
use Filament\Actions\Action;
|
||||
|
||||
Action::make('quickView')
|
||||
->dispatch('quickView', [$record->id])
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\GlobalSearch\Actions;
|
||||
|
||||
use Filament\Actions\StaticAction;
|
||||
use Filament\Support\Enums\ActionSize;
|
||||
|
||||
class Action extends StaticAction
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->defaultView(static::LINK_VIEW);
|
||||
|
||||
$this->defaultSize(ActionSize::Small);
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,17 @@
|
||||
|
||||
namespace Filament\GlobalSearch;
|
||||
|
||||
use Filament\GlobalSearch\Actions\Action;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Support\Enums\ActionSize;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
|
||||
class GlobalSearchResult
|
||||
{
|
||||
/**
|
||||
* @var array<Action>
|
||||
*/
|
||||
public readonly array $actions;
|
||||
|
||||
/**
|
||||
* @param array<string, string> $details
|
||||
* @param array<Action> $actions
|
||||
@@ -15,7 +21,13 @@ class GlobalSearchResult
|
||||
readonly public string | Htmlable $title,
|
||||
readonly public string $url,
|
||||
readonly public array $details = [],
|
||||
readonly public array $actions = [],
|
||||
array $actions = [],
|
||||
) {
|
||||
$this->actions = array_map(
|
||||
fn (Action $action) => $action
|
||||
->defaultView(Action::LINK_VIEW)
|
||||
->defaultSize(ActionSize::Small),
|
||||
$actions,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace Filament\Resources;
|
||||
|
||||
use Exception;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Clusters\Cluster;
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\GlobalSearch\Actions\Action;
|
||||
use Filament\GlobalSearch\GlobalSearchResult;
|
||||
use Filament\Navigation\NavigationGroup;
|
||||
use Filament\Navigation\NavigationItem;
|
||||
|
||||
@@ -13,7 +13,6 @@ use Filament\Support\Concerns\HasPlaceholder;
|
||||
use Filament\Support\Concerns\HasVerticalAlignment;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Traits\Conditionable;
|
||||
|
||||
class Column extends ViewComponent
|
||||
{
|
||||
@@ -42,7 +41,6 @@ class Column extends ViewComponent
|
||||
use Concerns\HasTooltip;
|
||||
use Concerns\HasWidth;
|
||||
use Concerns\InteractsWithTableQuery;
|
||||
use Conditionable;
|
||||
use HasAlignment;
|
||||
use HasCellState;
|
||||
use HasExtraAttributes;
|
||||
|
||||
@@ -16,7 +16,6 @@ use Filament\Tables\Columns\Concerns\HasRecord;
|
||||
use Filament\Tables\Columns\Concerns\HasRowLoopObject;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Traits\Conditionable;
|
||||
|
||||
class Component extends ViewComponent
|
||||
{
|
||||
@@ -25,7 +24,6 @@ class Component extends ViewComponent
|
||||
use CanBeHidden;
|
||||
use CanGrow;
|
||||
use CanSpanColumns;
|
||||
use Conditionable;
|
||||
use HasExtraAttributes;
|
||||
use HasRecord;
|
||||
use HasRowLoopObject;
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Filament\Tables\Concerns;
|
||||
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\ActionGroup;
|
||||
use Filament\Actions\BulkAction;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
@@ -32,7 +31,7 @@ trait HasHeader
|
||||
/**
|
||||
* @deprecated Override the `table()` method to configure the table.
|
||||
*
|
||||
* @return array<Action | BulkAction | ActionGroup>
|
||||
* @return array<Action | ActionGroup>
|
||||
*/
|
||||
protected function getTableHeaderActions(): array
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Filament\Tables\Filters;
|
||||
|
||||
use Exception;
|
||||
use Filament\Support\Components\Component;
|
||||
use Illuminate\Support\Traits\Conditionable;
|
||||
|
||||
class BaseFilter extends Component
|
||||
{
|
||||
@@ -19,7 +18,6 @@ class BaseFilter extends Component
|
||||
use Concerns\HasLabel;
|
||||
use Concerns\HasName;
|
||||
use Concerns\InteractsWithTableQuery;
|
||||
use Conditionable;
|
||||
|
||||
protected string $evaluationIdentifier = 'filter';
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@ return static function (RectorConfig $rectorConfig): void {
|
||||
'Filament\\Forms\\Components\\HasManyRepeater' => 'Filament\\Forms\\Components\\RelationshipRepeater',
|
||||
'Filament\\Forms\\Components\\MorphManyRepeater' => 'Filament\\Forms\\Components\\RelationshipRepeater',
|
||||
'Filament\\Actions\\Exceptions\\Hold' => 'Filament\\Support\\Exceptions\\Halt',
|
||||
'Filament\\Actions\\Modal\\Actions' => 'Filament\\Actions\\StaticAction',
|
||||
'Filament\\Actions\\Modal\\Actions' => 'Filament\\Actions\\Action',
|
||||
'Filament\\Forms\\Components\\Concerns\\HasExtraAlpineAttributes' => 'Filament\\Support\\Concerns\\HasExtraAlpineAttributes',
|
||||
'Filament\\Forms\\Components\\Concerns\\HasExtraAttributes' => 'Filament\\Support\\Concerns\\HasExtraAttributes',
|
||||
'Filament\\Infolists\\Components\\Card' => 'Filament\\Schema\\Components\\Section',
|
||||
'Filament\\Http\\Livewire\\Auth\\Login' => 'Filament\\Pages\\Auth\\Login',
|
||||
'Filament\\Navigation\\UserMenuItem' => 'Filament\\Navigation\\MenuItem',
|
||||
'Filament\\Pages\\Actions\\Modal\\Actions\\Action' => 'Filament\\Actions\\StaticAction',
|
||||
'Filament\\Pages\\Actions\\Modal\\Actions\\ButtonAction' => 'Filament\\Actions\\StaticAction',
|
||||
'Filament\\Pages\\Actions\\Modal\\Actions\\Action' => 'Filament\\Actions\\Action',
|
||||
'Filament\\Pages\\Actions\\Modal\\Actions\\ButtonAction' => 'Filament\\Actions\\Action',
|
||||
'Filament\\Pages\\Actions\\ActionGroup' => 'Filament\\Actions\\ActionGroup',
|
||||
'Filament\\Pages\\Actions\\ButtonAction' => 'Filament\\Actions\\Action',
|
||||
'Filament\\Pages\\Actions\\CreateAction' => 'Filament\\Actions\\CreateAction',
|
||||
@@ -46,8 +46,8 @@ return static function (RectorConfig $rectorConfig): void {
|
||||
'Filament\\Pages\\Actions\\SelectAction' => 'Filament\\Actions\\SelectAction',
|
||||
'Filament\\Pages\\Actions\\ViewAction' => 'Filament\\Actions\\ViewAction',
|
||||
'Filament\\Resources\\Pages\\ListRecords\\Tab' => 'Filament\\Resources\\Components\\Tab',
|
||||
'Filament\\Tables\\Actions\\Modal\\Actions\\Action' => 'Filament\\Actions\\StaticAction',
|
||||
'Filament\\Tables\\Actions\\Modal\\Actions\\ButtonAction' => 'Filament\\Actions\\StaticAction',
|
||||
'Filament\\Tables\\Actions\\Modal\\Actions\\Action' => 'Filament\\Actions\\Action',
|
||||
'Filament\\Tables\\Actions\\Modal\\Actions\\ButtonAction' => 'Filament\\Actions\\Action',
|
||||
'Filament\\Tables\\Actions\\LinkAction' => 'Filament\\Actions\\Action',
|
||||
'Filament\\Tables\\Columns\\Concerns\\HasExtraAttributes' => 'Filament\\Support\\Concerns\\HasExtraAttributes',
|
||||
'Filament\\Widgets\\StatsOverviewWidget\\Card' => 'Filament\\Widgets\\StatsOverviewWidget\\Stat',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use BladeUI\Icons\Factory;
|
||||
use BladeUI\Icons\IconsManifest;
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Notifications\Collection;
|
||||
use Filament\Notifications\Livewire\Notifications;
|
||||
use Filament\Notifications\Notification;
|
||||
|
||||
Reference in New Issue
Block a user