diff --git a/app/Filament/Resources/AiModels/AiModelResource.php b/app/Filament/Resources/AiModels/AiModelResource.php
index a40386d..871c5fb 100644
--- a/app/Filament/Resources/AiModels/AiModelResource.php
+++ b/app/Filament/Resources/AiModels/AiModelResource.php
@@ -2,29 +2,24 @@
namespace App\Filament\Resources\AiModels;
-use BackedEnum;
-use App\Filament\Resources\AiModels\Pages;
-use App\Filament\Resources\AiModels\RelationManagers;
-use App\Models\AiModel;
-use Filament\Schemas\Schema;
-use Filament\Resources\Resource;
-use Filament\Tables;
-use Filament\Tables\Table;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\IconColumn;
-use Illuminate\Database\Eloquent\SoftDeletingScope;
-use Illuminate\Database\Eloquent\Model;
-use App\Models\ApiProvider;
-use App\Api\Plugins\PluginLoader;
use App\Api\Plugins\ApiPluginInterface;
+use App\Api\Plugins\PluginLoader;
+use App\Models\AiModel;
+use App\Models\ApiProvider;
use Filament\Actions\Action;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
+use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
-use Filament\Forms\Components\Textarea;
+use Filament\Resources\Resource;
+use Filament\Schemas\Schema;
+use Filament\Tables\Columns\IconColumn;
+use Filament\Tables\Columns\TextColumn;
+use Filament\Tables\Table;
+use Illuminate\Database\Eloquent\Model;
class AiModelResource extends Resource
{
@@ -32,6 +27,13 @@ class AiModelResource extends Resource
// protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
+ protected static ?int $navigationSort = -100;
+
+ public static function getNavigationGroup(): ?string
+ {
+ return __('filament.navigation.groups.ai_models');
+ }
+
public static function form(Schema $schema): Schema
{
return $schema
@@ -49,16 +51,16 @@ class AiModelResource extends Resource
->rows(15),
]);
}
-
+
protected static function canSearchModelsWithAnyProvider(?array $apiProviderIds): bool
{
if (empty($apiProviderIds)) {
return false;
}
-
+
foreach ($apiProviderIds as $apiProviderId) {
$apiProvider = ApiProvider::find($apiProviderId);
- if (!$apiProvider || !$apiProvider->plugin) {
+ if (! $apiProvider || ! $apiProvider->plugin) {
continue;
}
try {
@@ -71,16 +73,17 @@ class AiModelResource extends Resource
continue;
}
}
+
return false;
}
protected static function getPluginInstance(?int $apiProviderId): ?ApiPluginInterface
{
- if (!$apiProviderId) {
+ if (! $apiProviderId) {
return null;
}
$apiProvider = ApiProvider::find($apiProviderId);
- if (!$apiProvider || !$apiProvider->plugin) {
+ if (! $apiProvider || ! $apiProvider->plugin) {
return null;
}
try {
@@ -93,15 +96,16 @@ class AiModelResource extends Resource
protected static function canSearchModels(?int $apiProviderId): bool
{
- if (!$apiProviderId) {
+ if (! $apiProviderId) {
return false;
}
$apiProvider = ApiProvider::find($apiProviderId);
- if (!$apiProvider || !$apiProvider->plugin) {
+ if (! $apiProvider || ! $apiProvider->plugin) {
return false;
}
try {
$pluginInstance = PluginLoader::getPlugin($apiProvider->plugin, $apiProvider);
+
return method_exists($pluginInstance, 'searchModels');
} catch (\Exception $e) {
// Log the exception if needed
@@ -141,14 +145,14 @@ class AiModelResource extends Resource
CreateAction::make(),
]);
}
-
+
public static function getRelations(): array
{
return [
//
];
}
-
+
public static function getPages(): array
{
return [
@@ -156,5 +160,5 @@ class AiModelResource extends Resource
'create' => Pages\CreateAiModel::route('/create'),
'edit' => Pages\EditAiModel::route('/{record}/edit'),
];
- }
+ }
}
diff --git a/app/Filament/Resources/ApiProviders/ApiProviderResource.php b/app/Filament/Resources/ApiProviders/ApiProviderResource.php
index 2a29221..6b0890a 100644
--- a/app/Filament/Resources/ApiProviders/ApiProviderResource.php
+++ b/app/Filament/Resources/ApiProviders/ApiProviderResource.php
@@ -2,28 +2,22 @@
namespace App\Filament\Resources\ApiProviders;
-use App\Filament\Resources\ApiProviders\Pages;
-use App\Filament\Resources\ApiProviders\RelationManagers;
+use App\Api\Plugins\ApiPluginInterface;
use App\Models\ApiProvider;
-use Filament\Schemas;
-use Filament\Schemas\Schema;
-use Filament\Resources\Resource;
-use Filament\Tables;
+use BackedEnum;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
-use Filament\Tables\Table;
-use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Database\Eloquent\SoftDeletingScope;
-use Filament\Forms\Components\TextInput;
-use Filament\Tables\Columns\TextColumn;
use Filament\Forms\Components\Select;
-use Illuminate\Support\Facades\File;
-use App\Api\Plugins\ApiPluginInterface;
+use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
+use Filament\Resources\Resource;
+use Filament\Schemas\Schema;
use Filament\Tables\Columns\IconColumn;
-use BackedEnum;
+use Filament\Tables\Columns\TextColumn;
+use Filament\Tables\Table;
+use Illuminate\Support\Facades\File;
class ApiProviderResource extends Resource
{
@@ -31,9 +25,17 @@ class ApiProviderResource extends Resource
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-rectangle-stack';
+ protected static ?int $navigationSort = -90;
+
+ public static function getNavigationGroup(): ?string
+ {
+ return __('filament.navigation.groups.ai_models');
+ }
+
public static function form(Schema $schema): Schema
{
$plugins = self::getAvailablePlugins();
+
return $schema
->components([
TextInput::make('name')
@@ -86,14 +88,14 @@ class ApiProviderResource extends Resource
CreateAction::make(),
]);
}
-
+
public static function getRelations(): array
{
return [
//
];
}
-
+
public static function getPages(): array
{
return [
@@ -102,23 +104,24 @@ class ApiProviderResource extends Resource
'edit' => Pages\EditApiProvider::route('/{record}/edit'),
];
}
-
+
protected static function getAvailablePlugins(): array
{
$plugins = [];
$path = app_path('Api/Plugins');
$files = File::files($path);
-
+
foreach ($files as $file) {
$filename = $file->getFilenameWithoutExtension();
if (in_array($filename, ['ApiPluginInterface', 'PluginLoader'])) {
continue;
}
- $class = "App\Api\Plugins\\" . $filename;
+ $class = "App\Api\Plugins\\".$filename;
if (class_exists($class) && in_array(ApiPluginInterface::class, class_implements($class))) {
$plugins[$filename] = $filename;
}
}
+
return $plugins;
}
}
diff --git a/app/Filament/Resources/Images/ImageResource.php b/app/Filament/Resources/Images/ImageResource.php
index 2b65048..5ba0273 100644
--- a/app/Filament/Resources/Images/ImageResource.php
+++ b/app/Filament/Resources/Images/ImageResource.php
@@ -2,25 +2,19 @@
namespace App\Filament\Resources\Images;
-use BackedEnum;
-use App\Filament\Resources\Images\Pages;
-use App\Filament\Resources\Images\RelationManagers;
use App\Models\Image;
-use Filament\Schemas;
-use Filament\Schemas\Schema;
-use Filament\Resources\Resource;
-use Filament\Tables;
-use Filament\Tables\Table;
-use Illuminate\Database\Eloquent\SoftDeletingScope;
-use Filament\Forms\Components\TextInput;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ImageColumn;
-use Filament\Forms\Components\FileUpload;
-use Filament\Forms\Components\Toggle;
+use BackedEnum;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
+use Filament\Forms\Components\FileUpload;
+use Filament\Forms\Components\Toggle;
+use Filament\Resources\Resource;
+use Filament\Schemas\Schema;
+use Filament\Tables\Columns\ImageColumn;
+use Filament\Tables\Columns\TextColumn;
+use Filament\Tables\Table;
class ImageResource extends Resource
{
@@ -28,6 +22,11 @@ class ImageResource extends Resource
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-rectangle-stack';
+ public static function getNavigationGroup(): ?string
+ {
+ return __('filament.navigation.groups.content');
+ }
+
public static function form(Schema $schema): Schema
{
return $schema
@@ -65,14 +64,14 @@ class ImageResource extends Resource
CreateAction::make(),
]);
}
-
+
public static function getRelations(): array
{
return [
//
];
}
-
+
public static function getPages(): array
{
return [
diff --git a/app/Filament/Resources/Roles/RoleResource.php b/app/Filament/Resources/Roles/RoleResource.php
index b435b81..3f8c84c 100644
--- a/app/Filament/Resources/Roles/RoleResource.php
+++ b/app/Filament/Resources/Roles/RoleResource.php
@@ -2,30 +2,28 @@
namespace App\Filament\Resources\Roles;
-use UnitEnum;
-use App\Filament\Resources\Roles\Pages;
-use App\Filament\Resources\Roles\RelationManagers;
use App\Models\Role;
-use Filament\Schemas;
-use Filament\Schemas\Schema;
-use Filament\Resources\Resource;
-use Filament\Tables;
-use Filament\Tables\Table;
-use Illuminate\Database\Eloquent\SoftDeletingScope;
-use Filament\Forms\Components\TextInput;
-use Filament\Tables\Columns\TextColumn;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
+use Filament\Forms\Components\TextInput;
+use Filament\Resources\Resource;
+use Filament\Schemas\Schema;
+use Filament\Tables\Columns\TextColumn;
+use Filament\Tables\Table;
+use UnitEnum;
class RoleResource extends Resource
{
protected static ?string $model = Role::class;
protected static UnitEnum|string|null $navigationGroup = 'User Management';
+
protected static ?string $navigationLabel = 'User Roles';
+ protected static bool $shouldRegisterNavigation = false;
+
public static function form(Schema $schema): Schema
{
return $schema
@@ -57,14 +55,14 @@ class RoleResource extends Resource
CreateAction::make(),
]);
}
-
+
public static function getRelations(): array
{
return [
//
];
}
-
+
public static function getPages(): array
{
return [
@@ -72,5 +70,5 @@ class RoleResource extends Resource
'create' => Pages\CreateRole::route('/create'),
'edit' => Pages\EditRole::route('/{record}/edit'),
];
- }
+ }
}
diff --git a/app/Filament/Resources/Styles/StyleResource.php b/app/Filament/Resources/Styles/StyleResource.php
index cb73c76..e89f870 100644
--- a/app/Filament/Resources/Styles/StyleResource.php
+++ b/app/Filament/Resources/Styles/StyleResource.php
@@ -1,38 +1,43 @@
icon('heroicon-o-document-duplicate')
->action(function (\App\Models\Style $record) {
$newStyle = $record->replicate();
- $newStyle->title = $record->title . ' (Kopie)';
+ $newStyle->title = $record->title.' (Kopie)';
$newStyle->save();
+
return redirect()->to(\App\Filament\Resources\Styles\StyleResource::getUrl('edit', ['record' => $newStyle->id]));
}),
])
@@ -135,14 +141,14 @@ class StyleResource extends Resource
CreateAction::make(),
]);
}
-
+
public static function getRelations(): array
{
return [
//
];
}
-
+
public static function getPages(): array
{
return [
@@ -150,5 +156,5 @@ class StyleResource extends Resource
'create' => Pages\CreateStyle::route('/create'),
'edit' => Pages\EditStyle::route('/{record}/edit'),
];
- }
+ }
}
diff --git a/app/Filament/Resources/Users/UserResource.php b/app/Filament/Resources/Users/UserResource.php
index afb8690..ec31f7c 100644
--- a/app/Filament/Resources/Users/UserResource.php
+++ b/app/Filament/Resources/Users/UserResource.php
@@ -2,31 +2,27 @@
namespace App\Filament\Resources\Users;
-use UnitEnum;
-use App\Filament\Resources\Users\Pages;
-use App\Filament\Resources\Users\RelationManagers;
use App\Models\User;
-use Filament\Schemas;
-use Filament\Schemas\Schema;
-use Filament\Resources\Resource;
-use Filament\Tables;
-use Filament\Tables\Table;
-use Illuminate\Database\Eloquent\SoftDeletingScope;
-use Filament\Forms\Components\TextInput;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Forms\Components\Select;
-use Filament\Schemas\Components\Section;
-use Filament\Forms\Components\Toggle;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
+use Filament\Forms\Components\Select;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\Toggle;
+use Filament\Resources\Resource;
+use Filament\Schemas\Components\Section;
+use Filament\Schemas\Schema;
+use Filament\Tables\Columns\TextColumn;
+use Filament\Tables\Table;
+use UnitEnum;
class UserResource extends Resource
{
protected static ?string $model = User::class;
protected static string|UnitEnum|null $navigationGroup = 'User Management';
+
protected static ?string $navigationLabel = 'Users';
public static function form(Schema $schema): Schema
@@ -98,14 +94,14 @@ class UserResource extends Resource
CreateAction::make(),
]);
}
-
+
public static function getRelations(): array
{
return [
//
];
}
-
+
public static function getPages(): array
{
return [
@@ -122,6 +118,6 @@ class UserResource extends Resource
public static function getNavigationLabel(): string
{
- return __('filament.navigation.user_roles');
- }
+ return __('filament.navigation.users');
+ }
}
diff --git a/database/seeders/AiModelSeeder.php b/database/seeders/AiModelSeeder.php
index 8612ee2..3d4003d 100644
--- a/database/seeders/AiModelSeeder.php
+++ b/database/seeders/AiModelSeeder.php
@@ -58,7 +58,251 @@ class AiModelSeeder extends Seeder
'model_id' => 'flux1-kontext-dev',
'api_provider_id' => null,
'enabled' => 1,
- 'parameters' => json_encode(['example' => 'parameter']),
+ 'parameters' => '{
+ "1": {
+ "inputs": {
+ "vae_name": "ae.safetensors"
+ },
+ "class_type": "VAELoader",
+ "_meta": {
+ "title": "Load VAE"
+ }
+ },
+ "2": {
+ "inputs": {
+ "clip_name1": "clip_l.safetensors",
+ "clip_name2": "t5xxl_fp8_e4m3fn_scaled.safetensors",
+ "type": "flux",
+ "device": "default"
+ },
+ "class_type": "DualCLIPLoader",
+ "_meta": {
+ "title": "DualCLIPLoader"
+ }
+ },
+ "3": {
+ "inputs": {
+ "conditioning": [
+ "25",
+ 0
+ ]
+ },
+ "class_type": "ConditioningZeroOut",
+ "_meta": {
+ "title": "ConditioningZeroOut"
+ }
+ },
+ "4": {
+ "inputs": {
+ "images": [
+ "9",
+ 0
+ ]
+ },
+ "class_type": "PreviewImage",
+ "_meta": {
+ "title": "Preview Image"
+ }
+ },
+ "5": {
+ "inputs": {
+ "filename_prefix": "ComfyUI",
+ "images": [
+ "7",
+ 0
+ ]
+ },
+ "class_type": "SaveImage",
+ "_meta": {
+ "title": "Save Image"
+ }
+ },
+ "7": {
+ "inputs": {
+ "samples": [
+ "20",
+ 0
+ ],
+ "vae": [
+ "1",
+ 0
+ ]
+ },
+ "class_type": "VAEDecode",
+ "_meta": {
+ "title": "VAE Decode"
+ }
+ },
+ "8": {
+ "inputs": {
+ "pixels": [
+ "9",
+ 0
+ ],
+ "vae": [
+ "1",
+ 0
+ ]
+ },
+ "class_type": "VAEEncode",
+ "_meta": {
+ "title": "VAE Encode"
+ }
+ },
+ "9": {
+ "inputs": {
+ "image": [
+ "27",
+ 0
+ ]
+ },
+ "class_type": "FluxKontextImageScale",
+ "_meta": {
+ "title": "FluxKontextImageScale"
+ }
+ },
+ "11": {
+ "inputs": {
+ "direction": "right",
+ "match_image_size": true,
+ "spacing_width": 0,
+ "spacing_color": "white",
+ "image1": [
+ "24",
+ 0
+ ]
+ },
+ "class_type": "ImageStitch",
+ "_meta": {
+ "title": "Image Stitch"
+ }
+ },
+ "12": {
+ "inputs": {
+ "guidance": 2.5,
+ "conditioning": [
+ "17",
+ 0
+ ]
+ },
+ "class_type": "FluxGuidance",
+ "_meta": {
+ "title": "FluxGuidance"
+ }
+ },
+ "17": {
+ "inputs": {
+ "conditioning": [
+ "25",
+ 0
+ ],
+ "latent": [
+ "8",
+ 0
+ ]
+ },
+ "class_type": "ReferenceLatent",
+ "_meta": {
+ "title": "ReferenceLatent"
+ }
+ },
+ "20": {
+ "inputs": {
+ "seed": 71319103185943,
+ "steps": 8,
+ "cfg": 1,
+ "sampler_name": "euler",
+ "scheduler": "simple",
+ "denoise": 1,
+ "model": [
+ "26",
+ 0
+ ],
+ "positive": [
+ "12",
+ 0
+ ],
+ "negative": [
+ "3",
+ 0
+ ],
+ "latent_image": [
+ "8",
+ 0
+ ]
+ },
+ "class_type": "KSampler",
+ "_meta": {
+ "title": "KSampler"
+ }
+ },
+ "22": {
+ "inputs": {
+ "model_path": "svdq-int4_r32-flux.1-kontext-dev.safetensors",
+ "cache_threshold": 0,
+ "attention": "nunchaku-fp16",
+ "cpu_offload": "auto",
+ "device_id": 0,
+ "data_type": "bfloat16",
+ "i2f_mode": "enabled"
+ },
+ "class_type": "NunchakuFluxDiTLoader",
+ "_meta": {
+ "title": "Nunchaku FLUX DiT Loader"
+ }
+ },
+ "24": {
+ "inputs": {
+ "image": "__FILENAME__",
+ "refresh": "refresh"
+ },
+ "class_type": "LoadImageOutput",
+ "_meta": {
+ "title": "Load Image (from Outputs)"
+ }
+ },
+ "25": {
+ "inputs": {
+ "text": "__PROMPT__",
+ "clip": [
+ "2",
+ 0
+ ]
+ },
+ "class_type": "CLIPTextEncode",
+ "_meta": {
+ "title": "CLIP Text Encode (Positive Prompt)"
+ }
+ },
+ "26": {
+ "inputs": {
+ "lora_name": "flux.1-kontext-dev-turbo_lora.safetensors",
+ "lora_strength": 1,
+ "model": [
+ "22",
+ 0
+ ]
+ },
+ "class_type": "NunchakuFluxLoraLoader",
+ "_meta": {
+ "title": "Nunchaku FLUX.1 LoRA Loader"
+ }
+ },
+ "27": {
+ "inputs": {
+ "upscale_method": "nearest-exact",
+ "megapixels": 1.2000000000000002,
+ "image": [
+ "11",
+ 0
+ ]
+ },
+ "class_type": "ImageScaleToTotalPixels",
+ "_meta": {
+ "title": "Scale Image to Total Pixels"
+ }
+ }
+ }',
],
[
'id' => 8,
diff --git a/resources/js/Components/ImageContextMenu.vue b/resources/js/Components/ImageContextMenu.vue
index 4aeb43b..c53f187 100644
--- a/resources/js/Components/ImageContextMenu.vue
+++ b/resources/js/Components/ImageContextMenu.vue
@@ -1,8 +1,11 @@
Menü Lass die KI dein Motiv verzaubern. Sofort den Druckdialog öffnen Datei lokal speichern Zurück zur Galerie {{ __('api.print_dialog.title') }}
Maximale Ausgabe pro Auftrag:
{{ maxCopies }}
@@ -16,9 +16,7 @@
@click="$emit('close')"
:aria-label="__('api.print_dialog.cancel_button')"
>
-
+ {{ style.title }} {{ style.description }}
{{ __('api.print_dialog.quantity_prompt') }}
+ {{ __('api.print_dialog.quantity_prompt') }}
+