Runware/ComfyUI fixes, dashboard links, import action, Leonardo plugin, widget, added status field and test connection button

This commit is contained in:
2025-12-03 14:48:45 +01:00
parent 3ec8e471bc
commit 090ec2c44b
16 changed files with 1019 additions and 142 deletions

View File

@@ -5,6 +5,7 @@ namespace App\Filament\Resources\Styles;
use App\Models\Style;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Actions\Action\Step;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\CreateAction;
@@ -25,6 +26,7 @@ use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Spatie\SimpleExcel\SimpleExcelReader;
class StyleResource extends Resource
{
@@ -107,6 +109,79 @@ class StyleResource extends Resource
->relationship('aiModel', 'name'),
])
->deferFilters(false)
->headerActions([
Action::make('import_styles')
->label('Import Styles (CSV)')
->icon('heroicon-o-arrow-up-on-square-stack')
->steps([
Step::make('Datei')
->schema([
FileUpload::make('import_file')
->label('CSV-Datei (Titel,Prompt,[Beschreibung])')
->acceptedFileTypes([
'text/csv',
'text/plain',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
])
->directory('imports/styles')
->visibility('private')
->required(),
]),
Step::make('Zuordnung')
->schema([
Select::make('ai_model_id')
->label('AI Modell')
->relationship('aiModel', 'name')
->required(),
]),
])
->action(function (array $data): void {
$path = storage_path('app/'.$data['import_file']);
if (! file_exists($path)) {
throw new \RuntimeException('Import-Datei nicht gefunden.');
}
$rows = self::parseImportFile($path);
if (empty($rows)) {
throw new \RuntimeException('Keine gültigen Zeilen gefunden.');
}
$created = 0;
foreach ($rows as $row) {
$title = $row['title'] ?? null;
$prompt = $row['prompt'] ?? null;
$description = $row['description'] ?? null;
if (! $title || ! $prompt) {
continue;
}
Style::create([
'title' => $title,
'prompt' => $prompt,
'description' => $description ?? '',
'preview_image' => '', // user must set later
'ai_model_id' => $data['ai_model_id'],
'enabled' => true,
'sort_order' => 0,
]);
$created++;
}
if ($created === 0) {
throw new \RuntimeException('Es wurden keine Styles importiert.');
}
\Filament\Notifications\Notification::make()
->title('Import abgeschlossen')
->body($created.' Styles importiert. Bitte Vorschau-Bilder ergänzen.')
->success()
->send();
}),
])
->actions([
EditAction::make(),
Action::make('duplicate')
@@ -149,6 +224,24 @@ class StyleResource extends Resource
];
}
protected static function parseImportFile(string $path): array
{
return SimpleExcelReader::create($path)->getRows()->map(function (array $row) {
$normalized = [];
foreach ($row as $key => $value) {
$normalized[strtolower(trim($key))] = is_string($value) ? trim($value) : $value;
}
return [
'title' => $normalized['title'] ?? $normalized['titel'] ?? null,
'prompt' => $normalized['prompt'] ?? null,
'description' => $normalized['description'] ?? $normalized['beschreibung'] ?? null,
];
})->filter(function (array $row) {
return ! empty($row['title']) && ! empty($row['prompt']);
})->values()->all();
}
public static function getPages(): array
{
return [