fix: Enhance feedback notifications for egg actions (#2042)

Co-authored-by: Charles <charles@pelican.dev>
This commit is contained in:
PalmarHealer
2026-01-15 18:32:50 +01:00
committed by GitHub
parent 943d9d3ef5
commit 675ab057b0
6 changed files with 100 additions and 37 deletions

View File

@@ -441,6 +441,16 @@ class EditEgg extends EditRecord
DeleteAction::make()
->disabled(fn (Egg $egg): bool => $egg->servers()->count() > 0)
->label(fn (Egg $egg): string => $egg->servers()->count() <= 0 ? trans('filament-actions::delete.single.label') : trans('admin/egg.in_use'))
->successNotification(fn (Egg $egg) => Notification::make()
->success()
->title(trans('admin/egg.delete_success'))
->body(trans('admin/egg.deleted', ['egg' => $egg->name]))
)
->failureNotification(fn (Egg $egg) => Notification::make()
->danger()
->title(trans('admin/egg.delete_failed'))
->body(trans('admin/egg.could_not_delete', ['egg' => $egg->name]))
)
->iconButton()->iconSize(IconSize::ExtraLarge),
ExportEggAction::make(),
ImportEggAction::make()

View File

@@ -18,11 +18,13 @@ use Filament\Actions\CreateAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\ReplicateAction;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords;
use Filament\Support\Enums\IconSize;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class ListEggs extends ListRecords
@@ -88,15 +90,45 @@ class ListEggs extends ListRecords
])
->groupedBulkActions([
DeleteBulkAction::make()
->before(fn (&$records) => $records = $records->filter(function ($egg) {
/** @var Egg $egg */
return $egg->servers_count <= 0;
})),
->before(function (Collection &$records) {
$eggsWithServers = $records->filter(fn (Egg $egg) => $egg->servers_count > 0);
if ($eggsWithServers->isNotEmpty()) {
$eggNames = $eggsWithServers->map(fn (Egg $egg) => sprintf('%s (%d server%s)', $egg->name, $egg->servers_count, $egg->servers_count > 1 ? 's' : ''))
->join(', ');
Notification::make()
->danger()
->title(trans('admin/egg.cannot_delete', ['count' => $eggsWithServers->count()]))
->body(trans('admin/egg.eggs_have_servers', ['eggs' => $eggNames]))
->send();
}
$records = $records->filter(fn (Egg $egg) => $egg->servers_count <= 0);
if ($records->isEmpty()) {
$this->halt();
}
}),
UpdateEggBulkAction::make()
->before(fn (&$records) => $records = $records->filter(function ($egg) {
/** @var Egg $egg */
return cache()->get("eggs.$egg->uuid.update", false);
})),
->before(function (Collection &$records) {
$eggsWithoutUpdateUrl = $records->filter(fn (Egg $egg) => $egg->update_url === null);
if ($eggsWithoutUpdateUrl->isNotEmpty()) {
$eggNames = $eggsWithoutUpdateUrl->pluck('name')->join(', ');
Notification::make()
->warning()
->title(trans('admin/egg.cannot_update', ['count' => $eggsWithoutUpdateUrl->count()]))
->body(trans('admin/egg.no_update_url', ['eggs' => $eggNames]))
->send();
}
$records = $records->filter(fn (Egg $egg) => $egg->update_url !== null);
if ($records->isEmpty()) {
$this->halt();
}
}),
])
->emptyStateIcon('tabler-eggs')
->emptyStateDescription('')

View File

@@ -89,18 +89,20 @@ class ImportEggAction extends Action
}
}
if ($failed->count() > 0) {
$bodyParts = collect([
$success->isNotEmpty() ? trans('admin/egg.import.imported_eggs', ['eggs' => $success->join(', ')]) : null,
$failed->isNotEmpty() ? trans('admin/egg.import.failed_import_eggs', ['eggs' => $failed->join(', ')]) : null,
])->filter();
if ($bodyParts->isNotEmpty()) {
Notification::make()
->title(trans('admin/egg.import.import_failed'))
->body($failed->join(', '))
->danger()
->send();
}
if ($success->count() > 0) {
Notification::make()
->title(trans('admin/egg.import.import_success'))
->body($success->join(', '))
->success()
->title(trans('admin/egg.import.import_result', [
'success' => $success->count(),
'failed' => $failed->count(),
'total' => $success->count() + $failed->count(),
]))
->body($bodyParts->join(' | '))
->status($failed->isEmpty() ? 'success' : ($success->isEmpty() ? 'danger' : 'warning'))
->send();
}
});

View File

@@ -47,8 +47,8 @@ class UpdateEggAction extends Action
cache()->forget("eggs.$egg->uuid.update");
} catch (Exception $exception) {
Notification::make()
->title(trans('admin/egg.update_failed'))
->body($exception->getMessage())
->title(trans('admin/egg.update_failed', ['egg' => $egg->name]))
->body(trans('admin/egg.update_error', ['error' => $exception->getMessage()]))
->danger()
->send();
@@ -58,8 +58,8 @@ class UpdateEggAction extends Action
}
Notification::make()
->title(trans_choice('admin/egg.updated', 1))
->body($egg->name)
->title(trans('admin/egg.update_success', ['egg' => $egg->name]))
->body(trans('admin/egg.updated_from', ['url' => $egg->update_url]))
->success()
->send();
});

View File

@@ -47,39 +47,40 @@ class UpdateEggBulkAction extends BulkAction
return;
}
$success = 0;
$failed = 0;
$skipped = 0;
$successEggs = collect();
$failedEggs = collect();
$skippedEggs = collect();
/** @var Egg $egg */
foreach ($records as $egg) {
if ($egg->update_url === null) {
$skipped++;
$skippedEggs->push($egg->name);
continue;
}
try {
$eggImporterService->fromUrl($egg->update_url, $egg);
$success++;
$successEggs->push($egg->name);
cache()->forget("eggs.$egg->uuid.update");
} catch (Exception $exception) {
$failed++;
$failedEggs->push($egg->name);
report($exception);
}
}
$bodyParts = collect([
$successEggs->isNotEmpty() ? trans('admin/egg.updated_eggs', ['eggs' => $successEggs->join(', ')]) : null,
$failedEggs->isNotEmpty() ? trans('admin/egg.failed_eggs', ['eggs' => $failedEggs->join(', ')]) : null,
$skippedEggs->isNotEmpty() ? trans('admin/egg.skipped_eggs', ['eggs' => $skippedEggs->join(', ')]) : null,
])->filter();
Notification::make()
->title(trans_choice('admin/egg.updated', 2, ['count' => $success, 'total' => $records->count()]))
->body(
collect([
$failed > 0 ? trans('admin/egg.updated_failed', ['count' => $failed]) : null,
$skipped > 0 ? trans('admin/egg.updated_skipped', ['count' => $skipped]) : null,
])->filter()->join(' ')
)
->status($failed > 0 ? 'warning' : 'success')
->title(trans_choice('admin/egg.updated', 2, ['count' => $successEggs->count(), 'total' => $records->count()]))
->body($bodyParts->join(' | '))
->status($failedEggs->isNotEmpty() ? 'warning' : 'success')
->persistent()
->send();
});

View File

@@ -21,6 +21,9 @@ return [
'add_url' => 'New URL',
'import_failed' => 'Import Failed',
'import_success' => 'Import Success',
'import_result' => 'Imported :success of :total eggs',
'imported_eggs' => 'Imported: :eggs',
'failed_import_eggs' => 'Failed: :eggs',
'github' => 'Add from Github',
'refresh' => 'Refresh',
'import_image' => 'Import Image',
@@ -102,7 +105,22 @@ return [
'updated' => 'Egg updated|:count/:total Eggs updated',
'updated_failed' => ':count failed',
'updated_skipped' => ':count skipped',
'update_success' => ':egg updated successfully',
'update_failed' => 'Failed to update :egg',
'update_question' => 'Are you sure you want to update this egg?|Are you sure you want to update the selected eggs?',
'update_description' => 'If you made any changes to the egg they will be overwritten!|If you made any changes to the eggs they will be overwritten!',
'no_updates' => 'No updates for the selected eggs available',
'cannot_update' => 'Cannot update :count egg(s)',
'no_update_url' => 'The following eggs do not have a working update URL set: :eggs',
'cannot_delete' => 'Cannot delete :count egg(s)',
'eggs_have_servers' => 'The following eggs have servers and cannot be deleted: :eggs',
'delete_success' => 'Egg deleted successfully',
'deleted' => 'Deleted: :egg',
'delete_failed' => 'Failed to delete egg',
'could_not_delete' => 'Could not delete: :egg',
'updated_from' => 'Successfully updated from: :url',
'update_error' => 'Error: :error',
'updated_eggs' => 'Updated: :eggs',
'failed_eggs' => 'Failed: :eggs',
'skipped_eggs' => 'Skipped: :eggs',
];