mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
Merge branch 'filamentphp:3.x' into configurable-export-routes
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
name: Unexpected v4 breaking change
|
||||
description: If a breaking change is not documented in the upgrade guide and not automatically upgraded by the script, report it here
|
||||
labels: unexpected major version breaking change,unconfirmed,high priority
|
||||
projects: ['filamentphp/2']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before opening a report, please search the existing issues (both open and closed).
|
||||
|
||||
---
|
||||
|
||||
Thank you for taking the time to file a report. To address this issue as fast as possible, we need some information.
|
||||
- type: dropdown
|
||||
id: package
|
||||
attributes:
|
||||
label: Package
|
||||
description: Which package is this report for?
|
||||
options:
|
||||
- filament/actions
|
||||
- filament/filament
|
||||
- filament/forms
|
||||
- filament/infolists
|
||||
- filament/notifications
|
||||
- filament/spark-billing-provider
|
||||
- filament/spatie-laravel-google-fonts-plugin
|
||||
- filament/spatie-laravel-media-library-plugin
|
||||
- filament/spatie-laravel-settings-plugin
|
||||
- filament/spatie-laravel-tags-plugin
|
||||
- filament/spatie-laravel-translatable-plugin
|
||||
- filament/support
|
||||
- filament/tables
|
||||
- filament/widgets
|
||||
- Other
|
||||
default: 1
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: package-version
|
||||
attributes:
|
||||
label: Package Version
|
||||
description: Please provide the full version of the package you have installed.
|
||||
placeholder: v3.0.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: laravel-version
|
||||
attributes:
|
||||
label: Laravel Version
|
||||
description: Please provide the full Laravel version of your project.
|
||||
placeholder: v10.0.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: livewire-version
|
||||
attributes:
|
||||
label: Livewire Version
|
||||
description: Please provide the full Livewire version of your project, if applicable.
|
||||
placeholder: v3.0.0
|
||||
- type: input
|
||||
id: php-version
|
||||
attributes:
|
||||
label: PHP Version
|
||||
description: Please provide the full PHP version of your server.
|
||||
placeholder: PHP 8.3.0
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Breaking change description
|
||||
description: What happened when you experienced the breaking change?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expectation
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: What did you expect to happen instead?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Which steps do we need to take to reproduce the problem? Any code examples need to be **as short as possible**, remove any code that is unrelated to the issue. **This issue will be automatically closed and not reviewed if detailed replication steps are missing.**
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction repository (issue will be closed if this is not valid)
|
||||
description: The URL of a public GitHub repository which reproduces the problem. **Please do not link to your actual project**, what we need instead is a _minimal_ reproduction in a fresh project without any unnecessary code. This means it doesn\'t matter if your real project is private / confidential, since we want a link to a separate, isolated reproduction. This allows us to fix the problem much quicker. **This issue will be automatically closed and not reviewed if this is missing. Please make sure to format the URL starting with `https://github.com` - only repositories hosted on GitHub are accepted.** [Need a headstart? We have a template Filament project for you.](https://filament-issue.unitedbycode.com)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: If applicable, provide relevant log output. No need for backticks here.
|
||||
render: shell
|
||||
@@ -0,0 +1,16 @@
|
||||
name: 'Deploy website on release'
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
forge-deploy:
|
||||
name: 'Laravel Forge Deploy'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Deploy
|
||||
uses: jbrooksuk/laravel-forge-action@v1.0.2
|
||||
with:
|
||||
trigger_url: ${{ secrets.WEBSITE_DEPLOYMENT_TRIGGER_URL }}
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v41
|
||||
uses: tj-actions/changed-files@v46
|
||||
with:
|
||||
files: |
|
||||
packages/**/resources/lang/en/**
|
||||
|
||||
Generated
+648
-277
File diff suppressed because it is too large
Load Diff
@@ -9,10 +9,10 @@
|
||||
"@tailwindcss/forms": "^0.5.2",
|
||||
"@tailwindcss/typography": "^0.5.4",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"laravel-vite-plugin": "^0.7.2",
|
||||
"laravel-vite-plugin": "^1.2.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-nesting": "^13.0.0",
|
||||
"tailwindcss": "^3.4.0",
|
||||
"vite": "^4.5.9"
|
||||
"vite": "^6.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +102,6 @@ trait InteractsWithActions
|
||||
$result = $action->callAfter() ?? $result;
|
||||
|
||||
$this->afterActionCalled();
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$action->rollBackDatabaseTransaction() :
|
||||
@@ -131,6 +129,8 @@ trait InteractsWithActions
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
|
||||
if (store($this)->has('redirect')) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,12 @@ class XlsxDownloader implements Downloader
|
||||
|
||||
if ($disk->exists($filePath = $directory . DIRECTORY_SEPARATOR . $fileName)) {
|
||||
$response = $disk->download($filePath);
|
||||
ob_end_clean();
|
||||
|
||||
if (ob_get_length() > 0) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
$response->headers->set('X-Vapor-Base64-Encode', 'True');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
+12
-12
File diff suppressed because one or more lines are too long
@@ -754,21 +754,30 @@ export default function fileUploadFormComponent({
|
||||
}
|
||||
}
|
||||
|
||||
import am from 'filepond/locale/am-et'
|
||||
import ar from 'filepond/locale/ar-ar'
|
||||
import az from 'filepond/locale/az-az'
|
||||
import ca from 'filepond/locale/ca-ca'
|
||||
import ckb from 'filepond/locale/ku-ckb'
|
||||
import cs from 'filepond/locale/cs-cz'
|
||||
import da from 'filepond/locale/da-dk'
|
||||
import de from 'filepond/locale/de-de'
|
||||
import el from 'filepond/locale/el-el'
|
||||
import en from 'filepond/locale/en-en'
|
||||
import es from 'filepond/locale/es-es'
|
||||
import fa from 'filepond/locale/fa_ir'
|
||||
import fi from 'filepond/locale/fi-fi'
|
||||
import fr from 'filepond/locale/fr-fr'
|
||||
import he from 'filepond/locale/he-he'
|
||||
import hr from 'filepond/locale/hr-hr'
|
||||
import hu from 'filepond/locale/hu-hu'
|
||||
import id from 'filepond/locale/id-id'
|
||||
import it from 'filepond/locale/it-it'
|
||||
import ja from 'filepond/locale/ja-ja'
|
||||
import km from 'filepond/locale/km-km'
|
||||
import ko from 'filepond/locale/ko-kr'
|
||||
import lt from 'filepond/locale/lt-lt'
|
||||
import lv from 'filepond/locale/lv-lv'
|
||||
import nl from 'filepond/locale/nl-nl'
|
||||
import no from 'filepond/locale/no_nb'
|
||||
import pl from 'filepond/locale/pl-pl'
|
||||
@@ -776,6 +785,7 @@ import pt_BR from 'filepond/locale/pt-br'
|
||||
import pt_PT from 'filepond/locale/pt-br'
|
||||
import ro from 'filepond/locale/ro-ro'
|
||||
import ru from 'filepond/locale/ru-ru'
|
||||
import sk from 'filepond/locale/sk-sk'
|
||||
import sv from 'filepond/locale/sv_se'
|
||||
import tr from 'filepond/locale/tr-tr'
|
||||
import uk from 'filepond/locale/uk-ua'
|
||||
@@ -784,21 +794,30 @@ import zh_CN from 'filepond/locale/zh-cn'
|
||||
import zh_TW from 'filepond/locale/zh-tw'
|
||||
|
||||
const locales = {
|
||||
am,
|
||||
ar,
|
||||
az,
|
||||
ca,
|
||||
ckb,
|
||||
cs,
|
||||
da,
|
||||
de,
|
||||
el,
|
||||
en,
|
||||
es,
|
||||
fa,
|
||||
fi,
|
||||
fr,
|
||||
he,
|
||||
hr,
|
||||
hu,
|
||||
id,
|
||||
it,
|
||||
ja,
|
||||
km,
|
||||
ko,
|
||||
lt,
|
||||
lv,
|
||||
nl,
|
||||
no,
|
||||
pl,
|
||||
@@ -806,6 +825,7 @@ const locales = {
|
||||
pt_PT,
|
||||
ro,
|
||||
ru,
|
||||
sk,
|
||||
sv,
|
||||
tr,
|
||||
uk,
|
||||
|
||||
@@ -8,7 +8,6 @@ use Illuminate\Filesystem\FilesystemAdapter;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use League\Flysystem\UnableToCheckFileExistence;
|
||||
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||
use SplFileInfo;
|
||||
use Throwable;
|
||||
|
||||
trait HasFileAttachments
|
||||
@@ -97,7 +96,7 @@ trait HasFileAttachments
|
||||
return $this->evaluate($this->fileAttachmentsVisibility);
|
||||
}
|
||||
|
||||
protected function handleFileAttachmentUpload(SplFileInfo $file): mixed
|
||||
protected function handleFileAttachmentUpload(TemporaryUploadedFile $file): mixed
|
||||
{
|
||||
$storeMethod = $this->getFileAttachmentsVisibility() === 'public' ? 'storePublicly' : 'store';
|
||||
|
||||
@@ -117,15 +116,15 @@ trait HasFileAttachments
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($storage->getVisibility($file) === 'private') {
|
||||
try {
|
||||
try {
|
||||
if ($storage->getVisibility($file) === 'private') {
|
||||
return $storage->temporaryUrl(
|
||||
$file,
|
||||
now()->addMinutes(5),
|
||||
);
|
||||
} catch (Throwable $exception) {
|
||||
// This driver does not support creating temporary URLs.
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
// This driver does not support creating temporary URLs.
|
||||
}
|
||||
|
||||
return $storage->url($file);
|
||||
|
||||
@@ -81,8 +81,6 @@ trait HasFormComponentActions
|
||||
]);
|
||||
|
||||
$result = $action->callAfter() ?? $result;
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$action->rollBackDatabaseTransaction() :
|
||||
@@ -110,6 +108,8 @@ trait HasFormComponentActions
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
|
||||
if (store($this)->has('redirect')) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
>
|
||||
@foreach ($limitedState as $stateItem)
|
||||
<img
|
||||
src="{{ filled($stateItem) ? $getImageUrl($stateItem) : $defaultImageUrl }}"
|
||||
src="{{ filled($stateItem) ? ($getImageUrl($stateItem) ?? $defaultImageUrl) : $defaultImageUrl }}"
|
||||
{{
|
||||
$getExtraImgAttributeBag()
|
||||
->class([
|
||||
|
||||
@@ -124,8 +124,6 @@ trait InteractsWithInfolists
|
||||
]);
|
||||
|
||||
$result = $action->callAfter() ?? $result;
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$action->rollBackDatabaseTransaction() :
|
||||
@@ -153,6 +151,8 @@ trait InteractsWithInfolists
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
|
||||
if (store($this)->has('redirect')) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -170,6 +170,45 @@ public function infolist(Infolist $infolist): Infolist
|
||||
}
|
||||
```
|
||||
|
||||
## Customizing relation managers for a specific view page
|
||||
|
||||
You can specify which relation managers should appear on a view page by defining a `getAllRelationManagers()` method:
|
||||
|
||||
```php
|
||||
protected function getAllRelationManagers(): array
|
||||
{
|
||||
return [
|
||||
CustomerAddressesRelationManager::class,
|
||||
CustomerContactsRelationManager::class,
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
This is useful when you have [multiple view pages](#creating-another-view-page) and need different relation managers on
|
||||
each page:
|
||||
|
||||
```php
|
||||
// ViewCustomer.php
|
||||
protected function getAllRelationManagers(): array
|
||||
{
|
||||
return [
|
||||
RelationManagers\OrdersRelationManager::class,
|
||||
RelationManagers\SubscriptionsRelationManager::class,
|
||||
];
|
||||
}
|
||||
|
||||
// ViewCustomerContact.php
|
||||
protected function getAllRelationManagers(): array
|
||||
{
|
||||
return [
|
||||
RelationManagers\ContactsRelationManager::class,
|
||||
RelationManagers\AddressesRelationManager::class,
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
If `getAllRelationManagers()` isn't defined, any relation managers defined in the resource will be used.
|
||||
|
||||
## Adding view pages to resource sub-navigation
|
||||
|
||||
If you're using [resource sub-navigation](getting-started#resource-sub-navigation), you can register this page as normal in `getRecordSubNavigation()` of the resource:
|
||||
|
||||
@@ -160,8 +160,6 @@ class EditProfile extends Page
|
||||
$this->handleRecordUpdate($this->getUser(), $data);
|
||||
|
||||
$this->callHook('afterSave');
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$this->rollBackDatabaseTransaction() :
|
||||
@@ -174,6 +172,8 @@ class EditProfile extends Page
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
|
||||
if (request()->hasSession() && array_key_exists('password', $data)) {
|
||||
request()->session()->put([
|
||||
'password_hash_' . Filament::getAuthGuard() => $data['password'],
|
||||
|
||||
@@ -125,8 +125,6 @@ abstract class EditTenantProfile extends Page
|
||||
$this->handleRecordUpdate($this->tenant, $data);
|
||||
|
||||
$this->callHook('afterSave');
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$this->rollBackDatabaseTransaction() :
|
||||
@@ -139,6 +137,8 @@ abstract class EditTenantProfile extends Page
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
|
||||
$this->getSavedNotification()?->send();
|
||||
|
||||
if ($redirectUrl = $this->getRedirectUrl()) {
|
||||
|
||||
@@ -91,8 +91,6 @@ abstract class RegisterTenant extends SimplePage
|
||||
$this->form->model($this->tenant)->saveRelationships();
|
||||
|
||||
$this->callHook('afterRegister');
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$this->rollBackDatabaseTransaction() :
|
||||
@@ -105,6 +103,8 @@ abstract class RegisterTenant extends SimplePage
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
|
||||
if ($redirectUrl = $this->getRedirectUrl()) {
|
||||
$this->redirect($redirectUrl, navigate: FilamentView::hasSpaMode() && is_app_url($redirectUrl));
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
namespace Filament\Panel\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Filament\AvatarProviders\UiAvatarsProvider;
|
||||
|
||||
trait HasAvatars
|
||||
{
|
||||
protected string $defaultAvatarProvider = UiAvatarsProvider::class;
|
||||
protected string | Closure $defaultAvatarProvider = UiAvatarsProvider::class;
|
||||
|
||||
public function defaultAvatarProvider(string $provider): static
|
||||
public function defaultAvatarProvider(string | Closure $provider): static
|
||||
{
|
||||
$this->defaultAvatarProvider = $provider;
|
||||
|
||||
@@ -17,6 +18,6 @@ trait HasAvatars
|
||||
|
||||
public function getDefaultAvatarProvider(): string
|
||||
{
|
||||
return $this->defaultAvatarProvider;
|
||||
return $this->evaluate($this->defaultAvatarProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,20 @@ trait HasRelationManagers
|
||||
#[Url]
|
||||
public ?string $activeRelationManager = null;
|
||||
|
||||
/**
|
||||
* @return array<class-string<RelationManager> | RelationGroup | RelationManagerConfiguration>
|
||||
*/
|
||||
protected function getAllRelationManagers(): array
|
||||
{
|
||||
return $this->getResource()::getRelations();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<RelationManager> | RelationGroup | RelationManagerConfiguration>
|
||||
*/
|
||||
public function getRelationManagers(): array
|
||||
{
|
||||
$managers = $this->getResource()::getRelations();
|
||||
$managers = $this->getAllRelationManagers();
|
||||
|
||||
return array_filter(
|
||||
$managers,
|
||||
|
||||
@@ -96,8 +96,6 @@ class CreateRecord extends Page
|
||||
$this->form->model($this->getRecord())->saveRelationships();
|
||||
|
||||
$this->callHook('afterCreate');
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$this->rollBackDatabaseTransaction() :
|
||||
@@ -110,6 +108,8 @@ class CreateRecord extends Page
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
|
||||
$this->rememberData();
|
||||
|
||||
$this->getCreatedNotification()?->send();
|
||||
|
||||
@@ -153,8 +153,6 @@ class EditRecord extends Page
|
||||
$this->handleRecordUpdate($this->getRecord(), $data);
|
||||
|
||||
$this->callHook('afterSave');
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$this->rollBackDatabaseTransaction() :
|
||||
@@ -167,6 +165,8 @@ class EditRecord extends Page
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
|
||||
$this->rememberData();
|
||||
|
||||
if ($shouldSendSavedNotification) {
|
||||
@@ -202,8 +202,6 @@ class EditRecord extends Page
|
||||
$this->handleRecordUpdate($this->getRecord(), $data);
|
||||
|
||||
$this->callHook('afterSave');
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$this->rollBackDatabaseTransaction() :
|
||||
@@ -216,6 +214,8 @@ class EditRecord extends Page
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
|
||||
$this->rememberData();
|
||||
}
|
||||
|
||||
|
||||
@@ -81,8 +81,6 @@ class SettingsPage extends Page
|
||||
$settings->save();
|
||||
|
||||
$this->callHook('afterSave');
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$this->rollBackDatabaseTransaction() :
|
||||
@@ -95,6 +93,8 @@ class SettingsPage extends Page
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
|
||||
$this->rememberData();
|
||||
|
||||
$this->getSavedNotification()?->send();
|
||||
|
||||
@@ -126,7 +126,7 @@ class CheckTranslationsCommand extends Command implements PromptsForMissingInput
|
||||
warning("[!] Package filament/{$package} has {$missingKeysCount} missing translation " . Str::plural('key', $missingKeysCount) . " and {$removedKeysCount} removed translation " . Str::plural('key', $removedKeysCount) . " for {$locale}.\n");
|
||||
} elseif ($missingKeysCount > 0) {
|
||||
warning("[!] Package filament/{$package} has {$missingKeysCount} missing translation " . Str::plural('key', $missingKeysCount) . " for {$locale}.\n");
|
||||
} elseif ($removedKeysCount > 0) {
|
||||
} else {
|
||||
warning("[!] Package filament/{$package} has {$removedKeysCount} removed translation " . Str::plural('key', $removedKeysCount) . " for {$locale}.\n");
|
||||
}
|
||||
})
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
>
|
||||
@foreach ($limitedState as $stateItem)
|
||||
<img
|
||||
src="{{ filled($stateItem) ? $getImageUrl($stateItem) : $defaultImageUrl }}"
|
||||
src="{{ filled($stateItem) ? ($getImageUrl($stateItem) ?? $defaultImageUrl) : $defaultImageUrl }}"
|
||||
{{
|
||||
$getExtraImgAttributeBag()
|
||||
->class([
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
@php
|
||||
$locale = app()->getLocale();
|
||||
@endphp
|
||||
|
||||
@props([
|
||||
'allSelectableRecordsCount',
|
||||
'deselectAllRecordsAction' => 'deselectAllRecords',
|
||||
@@ -30,7 +34,7 @@
|
||||
<span
|
||||
x-text="
|
||||
window.pluralize(@js(__('filament-tables::table.selection_indicator.selected_count')), {{ $selectedRecordsPropertyName }}.length, {
|
||||
count: {{ $selectedRecordsPropertyName }}.length,
|
||||
count: new Intl.NumberFormat(@js(str_replace('_', '-', $locale))).format({{ $selectedRecordsPropertyName }}.length),
|
||||
})
|
||||
"
|
||||
class="text-sm font-medium leading-6 text-gray-700 dark:text-gray-200"
|
||||
@@ -49,7 +53,7 @@
|
||||
{{-- Make sure the Alpine attributes get re-evaluated after a Livewire request: --}}
|
||||
:wire:key="$this->getId() . 'table.selection.indicator.actions.select-all.' . $allSelectableRecordsCount . '.' . $page"
|
||||
>
|
||||
{{ trans_choice('filament-tables::table.selection_indicator.actions.select_all.label', $allSelectableRecordsCount, ['count' => \Illuminate\Support\Number::format($allSelectableRecordsCount)]) }}
|
||||
{{ trans_choice('filament-tables::table.selection_indicator.actions.select_all.label', $allSelectableRecordsCount, ['count' => \Illuminate\Support\Number::format($allSelectableRecordsCount, locale: $locale)]) }}
|
||||
</x-filament::link>
|
||||
|
||||
<x-filament::link
|
||||
|
||||
@@ -113,8 +113,6 @@ trait HasActions
|
||||
]);
|
||||
|
||||
$result = $action->callAfter() ?? $result;
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$action->rollBackDatabaseTransaction() :
|
||||
@@ -142,6 +140,8 @@ trait HasActions
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
|
||||
if (store($this)->has('redirect')) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -84,8 +84,6 @@ trait HasBulkActions
|
||||
]);
|
||||
|
||||
$result = $action->callAfter() ?? $result;
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
$action->rollBackDatabaseTransaction() :
|
||||
@@ -113,6 +111,8 @@ trait HasBulkActions
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$action->commitDatabaseTransaction();
|
||||
|
||||
if (store($this)->has('redirect')) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ use Filament\Tables\Table;
|
||||
use Filament\Tests\Models\Post;
|
||||
use Filament\Tests\Panels\Fixtures\Resources\PostResource\Pages;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class PostResource extends Resource
|
||||
{
|
||||
@@ -57,6 +60,16 @@ class PostResource extends Resource
|
||||
->actions([
|
||||
Tables\Actions\ViewAction::make(),
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\Action::make('randomize_title')
|
||||
->databaseTransaction()
|
||||
->action(action: function (Post $record) {
|
||||
DB::afterCommit(function () {
|
||||
throw new RuntimeException('This exception, happening after the successful commit of the current transaction, should not trigger a rollback by Filament.');
|
||||
});
|
||||
|
||||
$record->title = Str::random(10);
|
||||
$record->save();
|
||||
}),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
|
||||
@@ -4,7 +4,10 @@ namespace Filament\Tests\Panels\Fixtures\Resources\PostResource\Pages;
|
||||
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use Filament\Tests\Models\Post;
|
||||
use Filament\Tests\Panels\Fixtures\Resources\PostResource;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use RuntimeException;
|
||||
|
||||
class EditPost extends EditRecord
|
||||
{
|
||||
@@ -17,6 +20,16 @@ class EditPost extends EditRecord
|
||||
Actions\ActionGroup::make([
|
||||
Actions\DeleteAction::make(),
|
||||
]),
|
||||
Actions\Action::make('randomize_title')
|
||||
->databaseTransaction()
|
||||
->action(action: function (Post $record) {
|
||||
DB::afterCommit(function () {
|
||||
throw new RuntimeException('This exception, happening after the successful commit of the current transaction, should not trigger a rollback by Filament.');
|
||||
});
|
||||
|
||||
$record->title = 'Test';
|
||||
$record->save();
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use Filament\Tests\Models\Post;
|
||||
use Filament\Tests\Panels\Fixtures\Resources\PostResource;
|
||||
use Filament\Tests\Panels\Fixtures\Resources\PostResource\Pages\EditPost;
|
||||
use Filament\Tests\Panels\Resources\TestCase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use function Filament\Tests\livewire;
|
||||
@@ -109,3 +110,23 @@ it('can refresh data', function () {
|
||||
'title' => $newPostTitle,
|
||||
]);
|
||||
});
|
||||
|
||||
test('actions will not interfere with database transactions on an error', function () {
|
||||
$post = Post::factory()->create();
|
||||
|
||||
$transactionLevel = DB::transactionLevel();
|
||||
|
||||
try {
|
||||
livewire(PostResource\Pages\EditPost::class, [
|
||||
'record' => $post->getKey(),
|
||||
])
|
||||
->callAction('randomize_title');
|
||||
} catch (Exception $e) {
|
||||
// This can be catched and handled somewhere else, code continues...
|
||||
}
|
||||
|
||||
// Original transaction level should be unaffected...
|
||||
|
||||
expect(DB::transactionLevel())
|
||||
->toBe($transactionLevel);
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ use Filament\Tests\Panels\Fixtures\Resources\PostResource;
|
||||
use Filament\Tests\Panels\Fixtures\Resources\PostResource\Pages\ListPosts;
|
||||
use Filament\Tests\Panels\Fixtures\Resources\UserResource;
|
||||
use Filament\Tests\Panels\Resources\TestCase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use function Filament\Tests\livewire;
|
||||
use function Pest\Laravel\assertSoftDeleted;
|
||||
@@ -115,3 +116,21 @@ it('can bulk delete posts', function () {
|
||||
assertSoftDeleted($post);
|
||||
}
|
||||
});
|
||||
|
||||
test('table actions will not interfere with database transactions on an error', function () {
|
||||
$post = Post::factory()->create();
|
||||
|
||||
$transactionLevel = DB::transactionLevel();
|
||||
|
||||
try {
|
||||
livewire(PostResource\Pages\ListPosts::class)
|
||||
->callTableAction('randomize_title', $post);
|
||||
} catch (Exception $e) {
|
||||
// This can be catched and handled somewhere else, code continues...
|
||||
}
|
||||
|
||||
// Original transaction level should be unaffected...
|
||||
|
||||
expect(DB::transactionLevel())
|
||||
->toBe($transactionLevel);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user