mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-01 15:09:33 +08:00
Modify import completed notification (#19714)
* add code * add for exports, clean up and docs --------- Co-authored-by: Dan Harrin <git@danharrin.com>
This commit is contained in:
@@ -693,6 +693,49 @@ ImportAction::make()
|
||||
|
||||
<UtilityInjection set="actions" version="4.x">As well as allowing a static value, the `headerOffset()` method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
|
||||
|
||||
## Customizing the completion notification
|
||||
|
||||
When an import finishes, Filament sends a notification to the user who started it. You can customize the title and body of that notification by overriding `getCompletedNotificationTitle()` and `getCompletedNotificationBody()` on your importer:
|
||||
|
||||
```php
|
||||
use Filament\Actions\Imports\Models\Import;
|
||||
|
||||
public static function getCompletedNotificationTitle(Import $import): string
|
||||
{
|
||||
return 'Your product import has finished';
|
||||
}
|
||||
|
||||
public static function getCompletedNotificationBody(Import $import): string
|
||||
{
|
||||
return $import->successful_rows . ' products were imported.';
|
||||
}
|
||||
```
|
||||
|
||||
For anything beyond the title and body — for example, changing the notification color, adding extra actions, or replacing the icon — override `modifyCompletedNotification()`. You can either mutate the `Notification` passed in and return it, or build and return a completely new one:
|
||||
|
||||
```php
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\Imports\Models\Import;
|
||||
use Filament\Notifications\Notification;
|
||||
|
||||
public static function modifyCompletedNotification(Notification $notification, Import $import): Notification
|
||||
{
|
||||
$notification->icon('heroicon-o-shopping-bag');
|
||||
|
||||
if ($import->getOptions()['sendWelcomeEmails'] ?? false) {
|
||||
$notification->actions([
|
||||
...$notification->getActions(),
|
||||
Action::make('viewWelcomeEmails')
|
||||
->url(route('emails.sent')),
|
||||
]);
|
||||
}
|
||||
|
||||
return $notification;
|
||||
}
|
||||
```
|
||||
|
||||
The `Import` model exposes the column mapping and options the user selected via `$import->getColumnMap()` and `$import->getOptions()`, so you can tailor the notification based on what the user imported.
|
||||
|
||||
## Customizing the import job
|
||||
|
||||
The default job for processing imports is `Filament\Actions\Imports\Jobs\ImportCsv`. If you want to extend this class and override any of its methods, you may replace the original class in the `register()` method of a service provider:
|
||||
|
||||
@@ -753,6 +753,49 @@ public function configureXlsxWriterBeforeClose(Writer $writer): Writer
|
||||
}
|
||||
```
|
||||
|
||||
## Customizing the completion notification
|
||||
|
||||
When an export finishes, Filament sends a notification to the user who started it. You can customize the title and body of that notification by overriding `getCompletedNotificationTitle()` and `getCompletedNotificationBody()` on your exporter:
|
||||
|
||||
```php
|
||||
use Filament\Actions\Exports\Models\Export;
|
||||
|
||||
public static function getCompletedNotificationTitle(Export $export): string
|
||||
{
|
||||
return 'Your product export is ready';
|
||||
}
|
||||
|
||||
public static function getCompletedNotificationBody(Export $export): string
|
||||
{
|
||||
return $export->successful_rows . ' products were exported.';
|
||||
}
|
||||
```
|
||||
|
||||
For anything beyond the title and body — for example, changing the notification color, adding extra actions, or replacing the icon — override `modifyCompletedNotification()`. You can either mutate the `Notification` passed in and return it, or build and return a completely new one:
|
||||
|
||||
```php
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\Exports\Models\Export;
|
||||
use Filament\Notifications\Notification;
|
||||
|
||||
public static function modifyCompletedNotification(Notification $notification, Export $export): Notification
|
||||
{
|
||||
$notification->icon('heroicon-o-shopping-bag');
|
||||
|
||||
if ($export->getOptions()['notifyTeam'] ?? false) {
|
||||
$notification->actions([
|
||||
...$notification->getActions(),
|
||||
Action::make('shareWithTeam')
|
||||
->url(route('exports.share', $export)),
|
||||
]);
|
||||
}
|
||||
|
||||
return $notification;
|
||||
}
|
||||
```
|
||||
|
||||
The `Export` model exposes the column mapping and options the user selected via `$export->getColumnMap()` and `$export->getOptions()`, so you can tailor the notification based on what the user exported.
|
||||
|
||||
## Customizing the export job
|
||||
|
||||
The default job for processing exports is `Filament\Actions\Exports\Jobs\PrepareCsvExport`. If you want to extend this class and override any of its methods, you may replace the original class in the `register()` method of a service provider:
|
||||
|
||||
@@ -8,6 +8,7 @@ use Filament\Actions\ActionGroup;
|
||||
use Filament\Actions\Exports\Enums\Contracts\ExportFormat as ExportFormatInterface;
|
||||
use Filament\Actions\Exports\Enums\ExportFormat;
|
||||
use Filament\Actions\Exports\Models\Export;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Schemas\Components\Component;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -96,6 +97,11 @@ abstract class Exporter
|
||||
return __('filament-actions::export.notifications.completed.title');
|
||||
}
|
||||
|
||||
public static function modifyCompletedNotification(Notification $notification, Export $export): Notification
|
||||
{
|
||||
return $notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, object>
|
||||
*/
|
||||
|
||||
@@ -51,9 +51,14 @@ class ExportCompletion implements ShouldQueue
|
||||
return;
|
||||
}
|
||||
|
||||
$this->export->columnMap($this->columnMap);
|
||||
$this->export->options($this->options);
|
||||
|
||||
$failedRowsCount = $this->export->getFailedRowsCount();
|
||||
|
||||
Notification::make()
|
||||
$isSynchronous = ($this->connection === 'sync') || (blank($this->connection) && (config('queue.default') === 'sync'));
|
||||
|
||||
$notification = Notification::make()
|
||||
->title($this->exporter::getCompletedNotificationTitle($this->export))
|
||||
->body($this->exporter::getCompletedNotificationBody($this->export))
|
||||
->when(
|
||||
@@ -76,12 +81,16 @@ class ExportCompletion implements ShouldQueue
|
||||
)),
|
||||
)
|
||||
->when(
|
||||
($this->connection === 'sync') ||
|
||||
(blank($this->connection) && (config('queue.default') === 'sync')),
|
||||
fn (Notification $notification) => $notification
|
||||
->persistent()
|
||||
->send(),
|
||||
fn (Notification $notification) => $notification->sendToDatabase($this->export->user, isEventDispatched: true),
|
||||
$isSynchronous,
|
||||
fn (Notification $notification) => $notification->persistent(),
|
||||
);
|
||||
|
||||
$notification = $this->exporter::modifyCompletedNotification($notification, $this->export);
|
||||
|
||||
if ($isSynchronous) {
|
||||
$notification->send();
|
||||
} else {
|
||||
$notification->sendToDatabase($this->export->user, isEventDispatched: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,16 @@ class Export extends Model
|
||||
{
|
||||
use Prunable;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected array $columnMap = [];
|
||||
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected array $options = [];
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
@@ -75,6 +85,9 @@ class Export extends Model
|
||||
array $columnMap,
|
||||
array $options,
|
||||
): Exporter {
|
||||
$this->columnMap($columnMap);
|
||||
$this->options($options);
|
||||
|
||||
return app($this->exporter, [
|
||||
'export' => $this,
|
||||
'columnMap' => $columnMap,
|
||||
@@ -82,6 +95,42 @@ class Export extends Model
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $columnMap
|
||||
*/
|
||||
public function columnMap(array $columnMap): static
|
||||
{
|
||||
$this->columnMap = $columnMap;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getColumnMap(): array
|
||||
{
|
||||
return $this->columnMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function options(array $options): static
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function getFailedRowsCount(): int
|
||||
{
|
||||
return $this->total_rows - $this->successful_rows;
|
||||
|
||||
@@ -284,9 +284,14 @@ class ImportAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
$import->columnMap($columnMap);
|
||||
$import->options($options);
|
||||
|
||||
$failedRowsCount = $import->getFailedRowsCount();
|
||||
|
||||
Notification::make()
|
||||
$isSynchronous = ($jobConnection === 'sync') || (blank($jobConnection) && (config('queue.default') === 'sync'));
|
||||
|
||||
$notification = Notification::make()
|
||||
->title($import->importer::getCompletedNotificationTitle($import))
|
||||
->body($import->importer::getCompletedNotificationBody($import))
|
||||
->when(
|
||||
@@ -314,13 +319,17 @@ class ImportAction extends Action
|
||||
]),
|
||||
)
|
||||
->when(
|
||||
($jobConnection === 'sync') ||
|
||||
(blank($jobConnection) && (config('queue.default') === 'sync')),
|
||||
fn (Notification $notification) => $notification
|
||||
->persistent()
|
||||
->send(),
|
||||
fn (Notification $notification) => $notification->sendToDatabase($import->user, isEventDispatched: true),
|
||||
$isSynchronous,
|
||||
fn (Notification $notification) => $notification->persistent(),
|
||||
);
|
||||
|
||||
$notification = $import->importer::modifyCompletedNotification($notification, $import);
|
||||
|
||||
if ($isSynchronous) {
|
||||
$notification->send();
|
||||
} else {
|
||||
$notification->sendToDatabase($import->user, isEventDispatched: true);
|
||||
}
|
||||
})
|
||||
->dispatch();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use Carbon\CarbonInterface;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\ActionGroup;
|
||||
use Filament\Actions\Imports\Models\Import;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Schemas\Components\Component;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
@@ -313,6 +314,11 @@ abstract class Importer
|
||||
return __('filament-actions::import.notifications.completed.title');
|
||||
}
|
||||
|
||||
public static function modifyCompletedNotification(Notification $notification, Import $import): Notification
|
||||
{
|
||||
return $notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, object>
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,16 @@ class Import extends Model
|
||||
{
|
||||
use Prunable;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected array $columnMap = [];
|
||||
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected array $options = [];
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
@@ -81,6 +91,9 @@ class Import extends Model
|
||||
array $columnMap,
|
||||
array $options,
|
||||
): Importer {
|
||||
$this->columnMap($columnMap);
|
||||
$this->options($options);
|
||||
|
||||
return app($this->importer, [
|
||||
'import' => $this,
|
||||
'columnMap' => $columnMap,
|
||||
@@ -88,6 +101,42 @@ class Import extends Model
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $columnMap
|
||||
*/
|
||||
public function columnMap(array $columnMap): static
|
||||
{
|
||||
$this->columnMap = $columnMap;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getColumnMap(): array
|
||||
{
|
||||
return $this->columnMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function options(array $options): static
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function getFailedRowsCount(): int
|
||||
{
|
||||
return $this->total_rows - $this->successful_rows;
|
||||
|
||||
Reference in New Issue
Block a user