Merge branch '3.x' into 4.x

This commit is contained in:
Dan Harrin
2024-07-12 11:23:54 +01:00
43 changed files with 128 additions and 100 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -19,4 +19,21 @@ trait BelongsToGroup
{
return $this->group;
}
public function getRootGroup(): ?ActionGroup
{
$group = $this->getGroup();
while ($group) {
$parentGroup = $group->getGroup();
if (! $parentGroup) {
break;
}
$group = $parentGroup;
}
return $group;
}
}
+1 -2
View File
@@ -28,8 +28,7 @@ abstract class Exporter
protected Export $export,
protected array $columnMap,
protected array $options,
) {
}
) {}
/**
* @return array<mixed>
@@ -47,6 +47,7 @@ class Export extends Model
$authenticatable = app(Authenticatable::class);
if ($authenticatable) {
/** @phpstan-ignore-next-line */
return $this->belongsTo($authenticatable::class);
}
@@ -54,6 +55,7 @@ class Export extends Model
throw new Exception('No [App\\Models\\User] model found. Please bind an authenticatable model to the [Illuminate\\Contracts\\Auth\\Authenticatable] interface in a service provider\'s [register()] method.');
}
/** @phpstan-ignore-next-line */
return $this->belongsTo(User::class);
}
@@ -4,6 +4,4 @@ namespace Filament\Actions\Imports\Exceptions;
use Exception;
class RowImportFailedException extends Exception
{
}
class RowImportFailedException extends Exception {}
+1 -2
View File
@@ -37,8 +37,7 @@ abstract class Importer
protected Import $import,
protected array $columnMap,
protected array $options,
) {
}
) {}
/**
* @param array<string, mixed> $data
@@ -53,6 +53,7 @@ class Import extends Model
$authenticatable = app(Authenticatable::class);
if ($authenticatable) {
/** @phpstan-ignore-next-line */
return $this->belongsTo($authenticatable::class);
}
@@ -60,6 +61,7 @@ class Import extends Model
throw new Exception('No [App\\Models\\User] model found. Please bind an authenticatable model to the [Illuminate\\Contracts\\Auth\\Authenticatable] interface in a service provider\'s [register()] method.');
}
/** @phpstan-ignore-next-line */
return $this->belongsTo(User::class);
}
+1 -3
View File
@@ -2,6 +2,4 @@
namespace Filament\Forms\Components;
class ViewField extends Field
{
}
class ViewField extends Field {}
@@ -2,6 +2,4 @@
namespace Filament\Infolists\Components;
class ViewEntry extends Entry
{
}
class ViewEntry extends Entry {}
@@ -425,3 +425,55 @@ import { Notification, NotificationAction } from '../../vendor/filament/notifica
// ...
```
## Closing a notification with JavaScript
Once a notification has been sent, you can close it on demand by dispatching a browser event on the window called `close-notification`.
The event needs to contain the ID of the notification you sent. To get the ID, you can use the `getId()` method on the `Notification` object:
```php
use Filament\Notifications\Notification;
$notification = Notification::make()
->title('Hello')
->persistent()
->send()
$notificationId = $notification->getId()
```
To close the notification, you can dispatch the event from Livewire:
```php
$this->dispatch('close-notification', id: $notificationId);
```
Or from JavaScript, in this case Alpine.js:
```blade
<button x-on:click="$dispatch('close-notification', { id: notificationId })" type="button">
Close Notification
</button>
```
If you are able to retrieve the notification ID, persist it, and then use it to close the notification, that is the recommended approach, as IDs are generated uniquely, and you will not risk closing the wrong notification. However, if it is not possible to persist the random ID, you can pass in a custom ID when sending the notification:
```php
use Filament\Notifications\Notification;
Notification::make('greeting')
->title('Hello')
->persistent()
->send()
```
In this case, you can close the notification by dispatching the event with the custom ID:
```blade
<button x-on:click="$dispatch('close-notification', { id: 'greeting' })" type="button">
Close Notification
</button>
```
Please be aware that if you send multiple notifications with the same ID, you may experience unexpected side effects, so random IDs are recommended.
@@ -8,6 +8,7 @@
$attributes
->merge([
'wire:key' => "{$this->getId()}.notifications.{$notification->getId()}",
'x-on:close-notification.window' => "if (\$event.detail.id == '{$notification->getId()}') close()",
], escape: false)
->class(['pointer-events-auto invisible'])
}}
@@ -17,8 +17,7 @@ class BroadcastNotification extends BaseNotification implements ShouldQueue
*/
public function __construct(
public array $data,
) {
}
) {}
/**
* @param Model $notifiable
@@ -17,8 +17,7 @@ class DatabaseNotification extends BaseNotification implements Arrayable, Should
*/
public function __construct(
public array $data,
) {
}
) {}
/**
* @param Model $notifiable
@@ -29,9 +29,7 @@ class DatabaseNotifications extends Component
public static ?string $authGuard = null;
#[On('databaseNotificationsSent')]
public function refresh(): void
{
}
public function refresh(): void {}
#[On('notificationClosed')]
public function removeNotification(string $id): void
@@ -15,7 +15,7 @@
<li
x-data="{ label: @js($subNavigation ? "sub_navigation_{$label}" : $label) }"
data-group-label="{{ $label }}"
data-group-label="{{ $subNavigation ? "sub_navigation_{$label}" : $label }}"
{{
$attributes->class([
'fi-sidebar-group flex flex-col gap-y-1',
@@ -11,8 +11,7 @@ class Registered
public function __construct(
protected Authenticatable $user,
) {
}
) {}
public function getUser(): Authenticatable
{
+1 -2
View File
@@ -14,8 +14,7 @@ class TenantSet
public function __construct(
protected Model $tenant,
protected Model | Authenticatable | HasTenants $user,
) {
}
) {}
public function getTenant(): Model
{
@@ -4,6 +4,4 @@ namespace Filament\Http\Responses\Auth\Contracts;
use Illuminate\Contracts\Support\Responsable;
interface EmailVerificationResponse extends Responsable
{
}
interface EmailVerificationResponse extends Responsable {}
@@ -4,6 +4,4 @@ namespace Filament\Http\Responses\Auth\Contracts;
use Illuminate\Contracts\Support\Responsable;
interface LoginResponse extends Responsable
{
}
interface LoginResponse extends Responsable {}
@@ -4,6 +4,4 @@ namespace Filament\Http\Responses\Auth\Contracts;
use Illuminate\Contracts\Support\Responsable;
interface LogoutResponse extends Responsable
{
}
interface LogoutResponse extends Responsable {}
@@ -4,6 +4,4 @@ namespace Filament\Http\Responses\Auth\Contracts;
use Illuminate\Contracts\Support\Responsable;
interface PasswordResetResponse extends Responsable
{
}
interface PasswordResetResponse extends Responsable {}
@@ -4,6 +4,4 @@ namespace Filament\Http\Responses\Auth\Contracts;
use Illuminate\Contracts\Support\Responsable;
interface RegistrationResponse extends Responsable
{
}
interface RegistrationResponse extends Responsable {}
+1 -3
View File
@@ -34,9 +34,7 @@ class MenuItem extends Component
protected bool | Closure $isVisible = true;
final public function __construct()
{
}
final public function __construct() {}
public static function make(): static
{
@@ -2,33 +2,35 @@
namespace Filament\Panel\Concerns;
use Closure;
trait HasSidebar
{
protected string $sidebarWidth = '20rem';
protected string $collapsedSidebarWidth = '4.5rem';
protected bool $isSidebarCollapsibleOnDesktop = false;
protected bool | Closure $isSidebarCollapsibleOnDesktop = false;
protected bool $isSidebarFullyCollapsibleOnDesktop = false;
protected bool | Closure $isSidebarFullyCollapsibleOnDesktop = false;
protected bool $hasCollapsibleNavigationGroups = true;
protected bool | Closure $hasCollapsibleNavigationGroups = true;
public function sidebarCollapsibleOnDesktop(bool $condition = true): static
public function sidebarCollapsibleOnDesktop(bool | Closure $condition = true): static
{
$this->isSidebarCollapsibleOnDesktop = $condition;
return $this;
}
public function sidebarFullyCollapsibleOnDesktop(bool $condition = true): static
public function sidebarFullyCollapsibleOnDesktop(bool | Closure $condition = true): static
{
$this->isSidebarFullyCollapsibleOnDesktop = $condition;
return $this;
}
public function collapsibleNavigationGroups(bool $condition = true): static
public function collapsibleNavigationGroups(bool | Closure $condition = true): static
{
$this->hasCollapsibleNavigationGroups = $condition;
@@ -61,16 +63,16 @@ trait HasSidebar
public function isSidebarCollapsibleOnDesktop(): bool
{
return $this->isSidebarCollapsibleOnDesktop;
return (bool) $this->evaluate($this->isSidebarCollapsibleOnDesktop);
}
public function isSidebarFullyCollapsibleOnDesktop(): bool
{
return $this->isSidebarFullyCollapsibleOnDesktop;
return (bool) $this->evaluate($this->isSidebarFullyCollapsibleOnDesktop);
}
public function hasCollapsibleNavigationGroups(): bool
{
return $this->hasCollapsibleNavigationGroups;
return (bool) $this->evaluate($this->hasCollapsibleNavigationGroups);
}
}
@@ -77,9 +77,7 @@ class ListRecords extends Page implements Tables\Contracts\HasTable
$this->loadDefaultActiveTab();
}
protected function authorizeAccess(): void
{
}
protected function authorizeAccess(): void {}
public function getBreadcrumb(): ?string
{
@@ -11,8 +11,7 @@ class PageRegistration
public function __construct(
protected string $page,
protected Closure $route,
) {
}
) {}
public function registerRoute(Panel $panel): ?Route
{
@@ -27,8 +27,7 @@ class RelationGroup extends Component
public function __construct(
protected string | Closure $label,
protected array | Closure $managers,
) {
}
) {}
/**
* @param array<class-string<RelationManager> | RelationManagerConfiguration> $managers
@@ -11,8 +11,7 @@ class RelationManagerConfiguration
public function __construct(
readonly public string $relationManager,
protected array $properties = [],
) {
}
) {}
/**
* @return array<string, mixed>
@@ -7,6 +7,4 @@ use Filament\Actions\LocaleSwitcher as BaseLocaleSwitcher;
/**
* @deprecated Use `\Filament\Actions\LocaleSwitcher` instead.
*/
class LocaleSwitcher extends BaseLocaleSwitcher
{
}
class LocaleSwitcher extends BaseLocaleSwitcher {}
@@ -12,9 +12,7 @@ use function Filament\Support\generate_search_column_expression;
class SpatieLaravelTranslatableContentDriver implements TranslatableContentDriver
{
public function __construct(protected string $activeLocale)
{
}
public function __construct(protected string $activeLocale) {}
public function isAttributeTranslatable(string $model, string $attribute): bool
{
@@ -14,9 +14,7 @@ class SpatieLaravelTranslatablePlugin implements Plugin
protected ?Closure $getLocaleLabelUsing = null;
final public function __construct()
{
}
final public function __construct() {}
public static function make(): static
{
+1 -3
View File
@@ -2,6 +2,4 @@
namespace Filament\Support\Assets;
class Theme extends Css
{
}
class Theme extends Css {}
+1 -2
View File
@@ -10,8 +10,7 @@ class ChunkIterator
public function __construct(
protected Iterator $iterator,
protected int $chunkSize,
) {
}
) {}
public function get(): Generator
{
@@ -24,9 +24,7 @@ class ComponentManager implements ScopedComponentManager
*/
protected array $methodCache = [];
final public function __construct()
{
}
final public function __construct() {}
public static function resolve(): ScopedComponentManager
{
@@ -27,7 +27,5 @@ trait Configurable
return $this;
}
protected function setUp(): void
{
}
protected function setUp(): void {}
}
+1 -2
View File
@@ -11,8 +11,7 @@ class Markdown implements Htmlable, Stringable
final public function __construct(
protected string $text,
protected bool $isInline = false,
) {
}
) {}
public static function inline(string $text): static
{
+1 -3
View File
@@ -2,6 +2,4 @@
namespace Filament\Tables\Columns;
class ViewColumn extends Column
{
}
class ViewColumn extends Column {}
@@ -21,9 +21,7 @@ trait HasBulkActions
protected Collection $cachedSelectedTableRecords;
protected function configureTableBulkAction(BulkAction $action): void
{
}
protected function configureTableBulkAction(BulkAction $action): void {}
/**
* @deprecated Use the `callMountedAction()` method instead.
+1 -2
View File
@@ -11,8 +11,7 @@ class WidgetConfiguration
public function __construct(
readonly public string $widget,
protected array $properties = [],
) {
}
) {}
/**
* @return array<string, mixed>
+2
View File
@@ -7,6 +7,8 @@ parameters:
excludePaths:
- packages/upgrade/*
reportUnmatchedIgnoredErrors: false
ignoreErrors:
- '#Unable to resolve the template type TKey in call to function collect#'
- '#Unable to resolve the template type TValue in call to function collect#'
+2 -6
View File
@@ -173,9 +173,5 @@ test('components can be visible based on Livewire component', function () {
->toHaveLength(1);
});
class Foo extends Livewire
{
}
class Bar extends Livewire
{
}
class Foo extends Livewire {}
class Bar extends Livewire {}
+5 -1
View File
@@ -278,13 +278,17 @@ it('can call an action and halt', function () {
});
it('can hide an action', function () {
$post = Post::factory()->create();
livewire(PostsTable::class)
->assertActionVisible(TestAction::make('visible')->table())
->assertActionHidden(TestAction::make('hidden')->table());
livewire(PostsTable::class)
->assertTableActionVisible('visible')
->assertTableActionHidden('hidden');
->assertTableActionHidden('hidden')
->assertTableActionVisible('groupedWithVisibleGroupCondition', $post)
->assertTableActionHidden('groupedWithHiddenGroupCondition', $post);
});
it('can disable an action', function () {