mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
Merge remote-tracking branch 'origin/3.x' into 3.x
This commit is contained in:
@@ -27,6 +27,10 @@
|
||||
:wire:key="$action ? $this->getId() . '.actions.' . $action->getName() . '.modal' : null"
|
||||
x-on:closed-form-component-action-modal.window="if (($event.detail.id === '{{ $this->getId() }}') && $wire.mountedActions.length) open()"
|
||||
x-on:modal-closed.stop="
|
||||
if (!$event.detail?.id?.startsWith('{{ $this->getId() }}-')) {
|
||||
return
|
||||
}
|
||||
|
||||
const mountedActionShouldOpenModal = {{ \Illuminate\Support\Js::from($action && $this->mountedActionShouldOpenModal(mountedAction: $action)) }}
|
||||
|
||||
if (! mountedActionShouldOpenModal) {
|
||||
@@ -89,6 +93,10 @@
|
||||
:wire:key="$action ? $this->getId() . '.table.actions.' . $action->getName() . '.modal' : null"
|
||||
x-on:closed-form-component-action-modal.window="if (($event.detail.id === '{{ $this->getId() }}') && $wire.mountedTableActions.length) open()"
|
||||
x-on:modal-closed.stop="
|
||||
if (!$event.detail?.id?.startsWith('{{ $this->getId() }}-')) {
|
||||
return
|
||||
}
|
||||
|
||||
const mountedTableActionShouldOpenModal = {{ \Illuminate\Support\Js::from($action && $this->mountedTableActionShouldOpenModal(mountedAction: $action)) }}
|
||||
|
||||
if (! mountedTableActionShouldOpenModal) {
|
||||
@@ -145,6 +153,10 @@
|
||||
:wire:key="$action ? $this->getId() . '.table.bulk-actions.' . $action->getName() . '.modal' : null"
|
||||
x-on:closed-form-component-action-modal.window="if (($event.detail.id === '{{ $this->getId() }}') && $wire.mountedTableBulkAction) open()"
|
||||
x-on:modal-closed.stop="
|
||||
if (!$event.detail?.id?.startsWith('{{ $this->getId() }}-')) {
|
||||
return
|
||||
}
|
||||
|
||||
const mountedTableBulkActionShouldOpenModal = {{ \Illuminate\Support\Js::from($action && $this->mountedTableBulkActionShouldOpenModal(mountedBulkAction: $action)) }}
|
||||
|
||||
if (! mountedTableBulkActionShouldOpenModal) {
|
||||
@@ -207,6 +219,10 @@
|
||||
: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="
|
||||
if (!$event.detail?.id?.startsWith('{{ $this->getId() }}-')) {
|
||||
return
|
||||
}
|
||||
|
||||
const mountedInfolistActionShouldOpenModal = {{ \Illuminate\Support\Js::from($action && $this->mountedInfolistActionShouldOpenModal(mountedAction: $action)) }}
|
||||
|
||||
if (! mountedInfolistActionShouldOpenModal) {
|
||||
@@ -268,6 +284,10 @@
|
||||
:width="$action?->getModalWidth()"
|
||||
:wire:key="$action ? $this->getId() . '.' . $action->getComponent()->getStatePath() . '.actions.' . $action->getName() . '.modal' : null"
|
||||
x-on:modal-closed.stop="
|
||||
if (!$event.detail?.id?.startsWith('{{ $this->getId() }}-')) {
|
||||
return
|
||||
}
|
||||
|
||||
const mountedFormComponentActionShouldOpenModal = {{ \Illuminate\Support\Js::from($action && $this->mountedFormComponentActionShouldOpenModal()) }}
|
||||
|
||||
if (mountedFormComponentActionShouldOpenModal) {
|
||||
|
||||
@@ -560,7 +560,7 @@ Group::make()
|
||||
|
||||
Please note that if you are saving the data to a `BelongsTo` relationship, then the foreign key column in your database must be `nullable()`. This is because Filament saves the form first, before saving the relationship. Since the form is saved first, the foreign ID does not exist yet, so it must be nullable. Immediately after the form is saved, Filament saves the relationship, which will then fill in the foreign ID and save it again.
|
||||
|
||||
It is worth noting that if you have an observer on your form model, then you may need to adapt it to ensure that it does not depend on the relationship existing when it it created. For example, if you have an observer that sends an email to a related record when a form is created, you may need to switch to using a different hook that runs after the relationship is attached, like `updated()`.
|
||||
It is worth noting that if you have an observer on your form model, then you may need to adapt it to ensure that it does not depend on the relationship existing when it is created. For example, if you have an observer that sends an email to a related record when a form is created, you may need to switch to using a different hook that runs after the relationship is attached, like `updated()`.
|
||||
|
||||
### Conditionally saving data to a relationship
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ return [
|
||||
'actions' => [
|
||||
|
||||
'deselect_all' => [
|
||||
'label' => 'Poista valinta kaikista',
|
||||
'label' => 'Poista valinnat',
|
||||
],
|
||||
|
||||
'select_all' => [
|
||||
@@ -408,6 +408,8 @@ return [
|
||||
|
||||
'create_option' => [
|
||||
|
||||
'label' => 'Uusi',
|
||||
|
||||
'modal' => [
|
||||
|
||||
'heading' => 'Uusi',
|
||||
@@ -430,6 +432,8 @@ return [
|
||||
|
||||
'edit_option' => [
|
||||
|
||||
'label' => 'Muokkaa',
|
||||
|
||||
'modal' => [
|
||||
|
||||
'heading' => 'Muokkaa',
|
||||
@@ -455,7 +459,7 @@ return [
|
||||
|
||||
'loading_message' => 'Ladataan...',
|
||||
|
||||
'max_items_message' => 'Vain :count voi valita.',
|
||||
'max_items_message' => 'Voit valita enintään :count.',
|
||||
|
||||
'no_search_results_message' => 'Haku ei löytänyt tuloksia.',
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@ return [
|
||||
'actions' => [
|
||||
|
||||
'create_option' => [
|
||||
|
||||
'label' => 'Créer',
|
||||
'modal' => [
|
||||
|
||||
'heading' => 'Créer',
|
||||
@@ -406,7 +406,7 @@ return [
|
||||
],
|
||||
|
||||
'edit_option' => [
|
||||
|
||||
'label' => 'Modifier',
|
||||
'modal' => [
|
||||
|
||||
'heading' => 'Modifier',
|
||||
|
||||
@@ -89,7 +89,7 @@ trait HasState
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function callAfterStateUpdated(): static
|
||||
public function callAfterStateUpdated(bool $shouldBubbleToParents = true): static
|
||||
{
|
||||
foreach ($this->afterStateUpdated as $callback) {
|
||||
$runId = spl_object_id($callback) . md5(json_encode($this->getState()));
|
||||
@@ -103,6 +103,10 @@ trait HasState
|
||||
store($this)->push('executedAfterStateUpdatedCallbacks', value: $runId, iKey: $runId);
|
||||
}
|
||||
|
||||
if ($shouldBubbleToParents) {
|
||||
$this->getContainer()->getParentComponent()?->callAfterStateUpdated();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -189,7 +193,7 @@ trait HasState
|
||||
// we need to dehydrate the child component containers while
|
||||
// informing them that they are not dehydrated, so that their
|
||||
// child components get removed from the state.
|
||||
foreach ($this->getChildComponentContainers() as $container) {
|
||||
foreach ($this->getChildComponentContainers(withHidden: true) as $container) {
|
||||
$container->dehydrateState($state, isDehydrated: false);
|
||||
}
|
||||
|
||||
|
||||
@@ -778,6 +778,14 @@ class Select extends Field implements Contracts\CanDisableOptions, Contracts\Has
|
||||
]) ?? $relationshipQuery;
|
||||
}
|
||||
|
||||
$baseRelationshipQuery = $relationshipQuery->getQuery();
|
||||
|
||||
if (isset($baseRelationshipQuery->limit)) {
|
||||
$component->optionsLimit($baseRelationshipQuery->limit);
|
||||
} elseif ($component->isSearchable() && filled($component->getSearchColumns())) {
|
||||
$relationshipQuery->limit($component->getOptionsLimit());
|
||||
}
|
||||
|
||||
$qualifiedRelatedKeyName = $component->getQualifiedRelatedKeyNameForRelationship($relationship);
|
||||
|
||||
if ($component->hasOptionLabelFromRecordUsingCallback()) {
|
||||
@@ -1081,7 +1089,7 @@ class Select extends Field implements Contracts\CanDisableOptions, Contracts\Has
|
||||
$query->where(function (Builder $query) use ($databaseConnection, $isForcedCaseInsensitive, $search): Builder {
|
||||
$isFirst = true;
|
||||
|
||||
foreach ($this->getSearchColumns() as $searchColumn) {
|
||||
foreach ($this->getSearchColumns() ?? [] as $searchColumn) {
|
||||
$whereClause = $isFirst ? 'where' : 'orWhere';
|
||||
|
||||
$query->{$whereClause}(
|
||||
@@ -1207,8 +1215,8 @@ class Select extends Field implements Contracts\CanDisableOptions, Contracts\Has
|
||||
|
||||
public function hasDynamicSearchResults(): bool
|
||||
{
|
||||
if ($this->hasRelationship() && empty($this->searchColumns)) {
|
||||
return ! $this->isPreloaded();
|
||||
if ($this->hasRelationship() && blank($this->getSearchColumns())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getSearchResultsUsing instanceof Closure;
|
||||
|
||||
@@ -27,13 +27,13 @@ trait HasState
|
||||
{
|
||||
foreach ($this->getComponents(withHidden: true) as $component) {
|
||||
if ($component->getStatePath() === $path) {
|
||||
$component->callAfterStateUpdated();
|
||||
$component->callAfterStateUpdated(shouldBubbleToParents: false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (str($path)->startsWith("{$component->getStatePath()}.")) {
|
||||
$component->callAfterStateUpdated();
|
||||
$component->callAfterStateUpdated(shouldBubbleToParents: false);
|
||||
}
|
||||
|
||||
foreach ($component->getChildComponentContainers() as $container) {
|
||||
|
||||
@@ -116,10 +116,6 @@
|
||||
|
||||
@if ($hasLimitedRemainingText && (! $isLimitedRemainingTextSeparate) && $isCircular)
|
||||
<div
|
||||
style="
|
||||
@if ($height) height: {{ $height }}; @endif
|
||||
@if ($width) width: {{ $width }}; @endif
|
||||
"
|
||||
@class([
|
||||
'flex items-center justify-center bg-gray-100 font-medium text-gray-500 dark:bg-gray-800 dark:text-gray-400',
|
||||
'rounded-full' => $isCircular,
|
||||
|
||||
@@ -215,6 +215,39 @@ class Dashboard extends BaseDashboard
|
||||
|
||||
Handling data from the filter action is the same as handling data from the filters header form, except that the data is validated before being passed to the widget. The `InteractsWithPageFilters` trait still applies.
|
||||
|
||||
### Persisting widget filters in the user's session
|
||||
|
||||
By default, the dashboard filters applied will persist in the user's session between page loads. To disable this, override the `$persistsFiltersInSession` property in the dashboard page class:
|
||||
|
||||
```php
|
||||
use Filament\Pages\Dashboard as BaseDashboard;
|
||||
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
|
||||
|
||||
class Dashboard extends BaseDashboard
|
||||
{
|
||||
use HasFiltersForm;
|
||||
|
||||
protected bool $persistsFiltersInSession = false;
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, override the `persistsFiltersInSession()` method in the dashboard page class:
|
||||
|
||||
```php
|
||||
use Filament\Pages\Dashboard as BaseDashboard;
|
||||
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
|
||||
|
||||
class Dashboard extends BaseDashboard
|
||||
{
|
||||
use HasFiltersForm;
|
||||
|
||||
public function persistsFiltersInSession(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Disabling the default widgets
|
||||
|
||||
By default, two widgets are displayed on the dashboard. These widgets can be disabled by updating the `widgets()` array of the [configuration](configuration):
|
||||
|
||||
@@ -4,7 +4,7 @@ return [
|
||||
|
||||
'field' => [
|
||||
'label' => 'Globaali haku',
|
||||
'placeholder' => 'Etsi',
|
||||
'placeholder' => 'Hae',
|
||||
],
|
||||
|
||||
'no_results_message' => 'Hakutuloksia ei löytynyt.',
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ return [
|
||||
'actions' => [
|
||||
|
||||
'resend_notification' => [
|
||||
'label' => 'Lähetä uudelleen ',
|
||||
'label' => 'Lähetä uudelleen',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
@@ -32,6 +32,10 @@ return [
|
||||
|
||||
'notifications' => [
|
||||
|
||||
'sent' => [
|
||||
'body' => 'Jos tiliä ei ole olemassa, et vastaanota sähköpostia.',
|
||||
],
|
||||
|
||||
'throttled' => [
|
||||
'title' => 'Liian monta pyyntöä',
|
||||
'body' => 'Yritä uudelleen :seconds sekunnin kuluttua.',
|
||||
|
||||
+4
@@ -32,6 +32,10 @@ return [
|
||||
|
||||
'notifications' => [
|
||||
|
||||
'sent' => [
|
||||
'body' => 'Se sua conta não existir, você não receberá o e-mail.',
|
||||
],
|
||||
|
||||
'throttled' => [
|
||||
'title' => 'Muitas solicitações',
|
||||
'body' => 'Por favor tente novamente em :seconds segundos.',
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ return [
|
||||
],
|
||||
|
||||
'messages' => [
|
||||
'notification_not_received' => 'Inte fått mejlet vi skickade?',
|
||||
'notification_not_received' => 'Inte fått meddelandet vi skickade?',
|
||||
'notification_sent' => 'Vi skickade ett meddelande till :email med instruktioner på hur du verifierar din mejladress.',
|
||||
],
|
||||
|
||||
|
||||
+5
-1
@@ -23,7 +23,7 @@ return [
|
||||
'actions' => [
|
||||
|
||||
'request' => [
|
||||
'label' => 'Skicka mejlmeddelande',
|
||||
'label' => 'Skicka meddelande',
|
||||
],
|
||||
|
||||
],
|
||||
@@ -32,6 +32,10 @@ return [
|
||||
|
||||
'notifications' => [
|
||||
|
||||
'sent' => [
|
||||
'body' => 'Om ditt konto inte finns, kommer du inte att få något meddelande.',
|
||||
],
|
||||
|
||||
'throttled' => [
|
||||
'title' => 'För många förfrågningar',
|
||||
'body' => 'Vänligen försök igen om :seconds sekunder.',
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
])
|
||||
>
|
||||
<head>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::HEAD_START, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::HEAD_START, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}" />
|
||||
@@ -31,7 +31,7 @@
|
||||
{{ filled($title) ? "{$title} - " : null }} {{ $brandName }}
|
||||
</title>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::STYLES_BEFORE, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::STYLES_BEFORE, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
<style>
|
||||
[x-cloak=''],
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
@stack('styles')
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::STYLES_AFTER, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::STYLES_AFTER, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
@if (! filament()->hasDarkMode())
|
||||
<script>
|
||||
@@ -100,7 +100,7 @@
|
||||
</script>
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::HEAD_END, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::HEAD_END, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
</head>
|
||||
|
||||
<body
|
||||
@@ -112,13 +112,13 @@
|
||||
'min-h-screen bg-gray-50 font-normal text-gray-950 antialiased dark:bg-gray-950 dark:text-white',
|
||||
]) }}
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::BODY_START, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::BODY_START, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
@livewire(Filament\Livewire\Notifications::class)
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SCRIPTS_BEFORE, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SCRIPTS_BEFORE, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
@filamentScripts(withCore: true)
|
||||
|
||||
@@ -138,8 +138,8 @@
|
||||
|
||||
@stack('scripts')
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SCRIPTS_AFTER, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SCRIPTS_AFTER, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::BODY_END, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::BODY_END, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
use Filament\Support\Enums\MaxWidth;
|
||||
|
||||
$navigation = filament()->getNavigation();
|
||||
$livewire ??= null;
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::layout.base :livewire="$livewire">
|
||||
@@ -34,11 +35,11 @@
|
||||
])
|
||||
>
|
||||
@if (filament()->hasTopbar())
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_BEFORE, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_BEFORE, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
<x-filament-panels::topbar :navigation="$navigation" />
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_AFTER, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_AFTER, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
@endif
|
||||
|
||||
<main
|
||||
@@ -70,14 +71,14 @@
|
||||
},
|
||||
])
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_START, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_START, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_END, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_END, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
</main>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::FOOTER, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::FOOTER, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
</div>
|
||||
|
||||
@if (filament()->hasNavigation())
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@php
|
||||
use Filament\Support\Enums\MaxWidth;
|
||||
|
||||
$livewire ??= null;
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::layout.base :livewire="$livewire">
|
||||
@@ -60,6 +62,6 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::FOOTER, scopes: $livewire->getRenderHookScopes()) }}
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::FOOTER, scopes: $livewire?->getRenderHookScopes()) }}
|
||||
</div>
|
||||
</x-filament-panels::layout.base>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'messages' => [
|
||||
'copied' => '已複製',
|
||||
],
|
||||
|
||||
];
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'actions' => [
|
||||
|
||||
'close' => [
|
||||
'label' => '關閉',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
@@ -9,17 +9,31 @@ return [
|
||||
'fields' => [
|
||||
|
||||
'records_per_page' => [
|
||||
|
||||
'label' => '每頁顯示',
|
||||
|
||||
'options' => [
|
||||
'all' => '全部',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
'actions' => [
|
||||
|
||||
'first' => [
|
||||
'label' => '第一頁',
|
||||
],
|
||||
|
||||
'go_to_page' => [
|
||||
'label' => '前往第 :page 頁',
|
||||
],
|
||||
|
||||
'last' => [
|
||||
'label' => '最後一頁',
|
||||
],
|
||||
|
||||
'next' => [
|
||||
'label' => '下一頁',
|
||||
],
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
this.isOpen = false
|
||||
|
||||
this.$refs.modalContainer.dispatchEvent(
|
||||
new CustomEvent('modal-closed', { id: '{{ $id }}' }),
|
||||
new CustomEvent('modal-closed', { detail: { id: '{{ $id }}' } }),
|
||||
)
|
||||
},
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
@endif
|
||||
|
||||
this.$refs.modalContainer.dispatchEvent(
|
||||
new CustomEvent('modal-opened', { id: '{{ $id }}' }),
|
||||
new CustomEvent('modal-opened', { detail: { id: '{{ $id }}' } }),
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -42,9 +42,9 @@ return [
|
||||
],
|
||||
|
||||
'search' => [
|
||||
'label' => 'Etsi',
|
||||
'placeholder' => 'Etsi',
|
||||
'indicator' => 'Etsi',
|
||||
'label' => 'Haku',
|
||||
'placeholder' => 'Hae',
|
||||
'indicator' => 'Haku',
|
||||
],
|
||||
|
||||
],
|
||||
@@ -118,7 +118,7 @@ return [
|
||||
'actions' => [
|
||||
|
||||
'apply' => [
|
||||
'label' => 'Käytä suodattimet',
|
||||
'label' => 'Aseta suodattimet',
|
||||
],
|
||||
|
||||
'remove' => [
|
||||
@@ -126,12 +126,12 @@ return [
|
||||
],
|
||||
|
||||
'remove_all' => [
|
||||
'label' => 'Poista suodattimet',
|
||||
'tooltip' => 'Poista suodattimet',
|
||||
'label' => 'Tyhjennä suodattimet',
|
||||
'tooltip' => 'Tyhjennä suodattimet',
|
||||
],
|
||||
|
||||
'reset' => [
|
||||
'label' => 'Tyhjennä suodattimet',
|
||||
'label' => 'Palauta',
|
||||
],
|
||||
|
||||
],
|
||||
@@ -173,7 +173,7 @@ return [
|
||||
|
||||
'direction' => [
|
||||
|
||||
'label' => 'Ryhmittelyn suunta',
|
||||
'label' => 'Ryhmitys',
|
||||
|
||||
'options' => [
|
||||
'asc' => 'Nousevasti',
|
||||
@@ -199,7 +199,7 @@ return [
|
||||
],
|
||||
|
||||
'deselect_all' => [
|
||||
'label' => 'Poista valinta kaikista',
|
||||
'label' => 'Poista valinnat',
|
||||
],
|
||||
|
||||
],
|
||||
@@ -216,7 +216,7 @@ return [
|
||||
|
||||
'direction' => [
|
||||
|
||||
'label' => 'Järjestyksen suunta',
|
||||
'label' => 'Järjestys',
|
||||
|
||||
'options' => [
|
||||
'asc' => 'Nousevasti',
|
||||
|
||||
@@ -102,10 +102,6 @@
|
||||
|
||||
@if ($hasLimitedRemainingText && (! $isLimitedRemainingTextSeparate) && $isCircular)
|
||||
<div
|
||||
style="
|
||||
@if ($height) height: {{ $height }}; @endif
|
||||
@if ($width) width: {{ $width }}; @endif
|
||||
"
|
||||
@class([
|
||||
'flex items-center justify-center bg-gray-100 font-medium text-gray-500 dark:bg-gray-800 dark:text-gray-400',
|
||||
'rounded-full' => $isCircular,
|
||||
|
||||
@@ -23,14 +23,18 @@
|
||||
@endif
|
||||
{{ $attributes->class(['fi-ta-header-cell px-3 py-3.5 sm:first-of-type:ps-6 sm:last-of-type:pe-6']) }}
|
||||
>
|
||||
<{{ $sortable ? 'button' : 'span' }}
|
||||
<span
|
||||
@if ($sortable)
|
||||
aria-label="{{ trim(strip_tags($slot)) }}"
|
||||
type="button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
wire:click="sortTable('{{ $name }}')"
|
||||
x-on:keydown.enter.prevent.stop="$wire.sortTable('{{ $name }}')"
|
||||
x-on:keydown.space.prevent.stop="$wire.sortTable('{{ $name }}')"
|
||||
@endif
|
||||
@class([
|
||||
'group flex w-full items-center gap-x-1',
|
||||
'cursor-pointer' => $sortable,
|
||||
'whitespace-nowrap' => ! $wrap,
|
||||
'whitespace-normal' => $wrap,
|
||||
match ($alignment) {
|
||||
@@ -67,5 +71,5 @@
|
||||
])
|
||||
/>
|
||||
@endif
|
||||
</{{ $sortable ? 'button' : 'span' }}>
|
||||
</span>
|
||||
</th>
|
||||
|
||||
@@ -640,7 +640,7 @@
|
||||
@if ($recordHasActions)
|
||||
<x-filament-tables::actions
|
||||
:actions="$actions"
|
||||
:alignment="(! $contentGrid) ? 'start md:end' : Alignment::Start"
|
||||
:alignment="(! $contentGrid) ? 'start md:end' : $actionsAlignment ?? Alignment::Start"
|
||||
:record="$record"
|
||||
wrap="-sm"
|
||||
:class="$recordActionsClasses"
|
||||
|
||||
@@ -599,6 +599,28 @@ test('hidden components are not excluded from state dehydration if there is anot
|
||||
->dehydrateState()->data->not()->toBe([]);
|
||||
});
|
||||
|
||||
test('components in a hidden parent component with a grandparent component with a state path are excluded from state dehydration', function () {
|
||||
$container = ComponentContainer::make(Livewire::make())
|
||||
->statePath('data')
|
||||
->components([
|
||||
(new Component)
|
||||
->statePath('data')
|
||||
->schema([
|
||||
(new Component)
|
||||
->schema([
|
||||
(new Component)
|
||||
->statePath(Str::random())
|
||||
->default(Str::random()),
|
||||
])
|
||||
->hidden(),
|
||||
]),
|
||||
])
|
||||
->fill();
|
||||
|
||||
expect($container)
|
||||
->dehydrateState()->toBe(['data' => ['data' => []]]);
|
||||
});
|
||||
|
||||
test('disabled components are excluded from state dehydration', function () {
|
||||
$container = ComponentContainer::make(Livewire::make())
|
||||
->statePath('data')
|
||||
|
||||
Reference in New Issue
Block a user