diff --git a/resources/views/filament/resources/product-resource/pages/list-products-footer.blade.php b/resources/views/filament/resources/product-resource/pages/list-products-footer.blade.php
deleted file mode 100644
index d4be8f0..0000000
--- a/resources/views/filament/resources/product-resource/pages/list-products-footer.blade.php
+++ /dev/null
@@ -1,311 +0,0 @@
-
-
-
-
-
-
-
-
-
![]()
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Filament/Forms/Components/ImageManager.php b/src/Filament/Forms/Components/ImageManager.php
index 8e32e67..6a862c7 100644
--- a/src/Filament/Forms/Components/ImageManager.php
+++ b/src/Filament/Forms/Components/ImageManager.php
@@ -11,6 +11,7 @@
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class ImageManager extends Field
@@ -84,7 +85,7 @@ protected function setUp(): void
$tempPath = storage_path('app/public/'.$item['temp_file']);
if (file_exists($tempPath)) {
$record->addMedia($tempPath)
- ->usingFileName($item['file_name'] ?? basename($tempPath))
+ ->usingFileName($this->sanitizeFilename($item['file_name'] ?? basename($tempPath)))
->withCustomProperties([
'name' => $item['name'] ?? [],
'description' => $item['description'] ?? [],
@@ -98,7 +99,7 @@ protected function setUp(): void
} elseif (isset($item['temp_url'])) {
try {
$record->addMediaFromUrl($item['temp_url'])
- ->usingFileName($item['file_name'] ?? basename($item['temp_url']))
+ ->usingFileName($this->sanitizeFilename($item['file_name'] ?? basename($item['temp_url'])))
->withCustomProperties([
'name' => $item['name'] ?? [],
'description' => $item['description'] ?? [],
@@ -213,7 +214,7 @@ public function getUploadAction(): Action
if (file_exists($fullPath)) {
$tempId = 'temp_'.uniqid();
- $fileName = basename($filePath);
+ $fileName = $this->sanitizeFilename(basename($filePath));
$currentState[] = [
'id' => null,
@@ -256,7 +257,7 @@ public function getUploadAction(): Action
if (file_exists($fullPath)) {
$record->addMedia($fullPath)
- ->usingFileName(basename($filePath))
+ ->usingFileName($this->sanitizeFilename(basename($filePath)))
->withCustomProperties([
'name' => [],
'description' => [],
@@ -331,7 +332,7 @@ public function getUrlUploadAction(): Action
'description' => [],
'is_cover' => count($currentState) === 0,
'position' => ++$maxPosition,
- 'file_name' => basename($url),
+ 'file_name' => $this->sanitizeFilename(basename($url)),
'mime_type' => 'image/*',
'size' => 0,
];
@@ -694,6 +695,21 @@ protected function ensureSingleCoverImage(Model $record): void
}
}
+ protected function sanitizeFilename(string $filename): string
+ {
+ $pathInfo = pathinfo($filename);
+ $name = $pathInfo['filename'] ?? 'image';
+ $extension = isset($pathInfo['extension']) ? '.'.$pathInfo['extension'] : '';
+
+ $sanitizedName = Str::slug($name, '-');
+
+ if (empty($sanitizedName)) {
+ $sanitizedName = 'image-'.time();
+ }
+
+ return $sanitizedName.$extension;
+ }
+
protected function cleanupOldTempFiles(): void
{
$tempDir = storage_path('app/public/temp-images');
diff --git a/src/Filament/Resources/ProductResource.php b/src/Filament/Resources/ProductResource.php
index 6af21e6..39474d8 100644
--- a/src/Filament/Resources/ProductResource.php
+++ b/src/Filament/Resources/ProductResource.php
@@ -4,6 +4,7 @@
use BezhanSalleh\FilamentShield\Contracts\HasShieldPermissions;
use Eclipse\Catalogue\Enums\PropertyInputType;
+use Eclipse\Catalogue\Enums\PropertyType;
use Eclipse\Catalogue\Filament\Filters\CustomPropertyConstraint;
use Eclipse\Catalogue\Filament\Forms\Components\ImageManager;
use Eclipse\Catalogue\Filament\Resources\ProductResource\Pages;
@@ -16,8 +17,11 @@
use Eclipse\Catalogue\Models\Property;
use Eclipse\Catalogue\Traits\HandlesTenantData;
use Eclipse\Catalogue\Traits\HasTenantFields;
+use Eclipse\Common\Filament\Tables\Columns\ImageColumn;
+use Eclipse\Common\Helpers\MediaHelper;
use Eclipse\World\Models\Country;
use Eclipse\World\Models\TariffCode;
+use Filament\Facades\Filament;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Radio;
@@ -44,7 +48,6 @@
use Filament\Tables\Actions\RestoreAction;
use Filament\Tables\Actions\RestoreBulkAction;
use Filament\Tables\Columns\IconColumn;
-use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\QueryBuilder;
use Filament\Tables\Filters\SelectFilter;
@@ -263,7 +266,7 @@ public static function form(Form $form): Form
'name',
function ($query) {
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
if ($tenantFK && $currentTenant) {
return $query->whereHas('productTypeData', function ($q) use ($tenantFK, $currentTenant) {
@@ -569,40 +572,26 @@ public static function table(Table $table): Table
->columns([
TextColumn::make('id'),
- ImageColumn::make('cover_image')
+ ImageColumn::make('images')
+ ->label('Images')
+ ->preview()
+ ->circular()
->stacked()
- ->label('Image')
- ->getStateUsing(function (Product $record) {
- $url = $record->getFirstMediaUrl('images', 'thumb');
+ ->getStateUsing(function (Product $record): array {
+ $images = $record->getMedia('images');
- return $url ?: null;
- })
- ->circular()
- ->defaultImageUrl(static::getPlaceholderImageUrl())
- ->extraImgAttributes(function (Product $record) {
- $coverMedia = $record->getMedia('images')
- ->filter(fn ($media) => $media->getCustomProperty('is_cover', false))
- ->first();
-
- if (! $coverMedia) {
- $coverMedia = $record->getMedia('images')->first();
+ if ($images->isEmpty()) {
+ if (class_exists(MediaHelper::class)) {
+ return [MediaHelper::getPlaceholderImageUrl()];
+ }
+
+ return [];
}
- $fullImageUrl = $coverMedia ? $coverMedia->getUrl() : null;
- $imageName = $coverMedia ? json_encode($coverMedia->getCustomProperty('name', [])) : '{}';
- $imageDescription = $coverMedia ? json_encode($coverMedia->getCustomProperty('description', [])) : '{}';
-
- return [
- 'class' => 'cursor-pointer product-image-trigger',
- 'data-url' => $fullImageUrl ?: static::getPlaceholderImageUrl(),
- 'data-image-name' => htmlspecialchars($imageName, ENT_QUOTES, 'UTF-8'),
- 'data-image-description' => htmlspecialchars($imageDescription, ENT_QUOTES, 'UTF-8'),
- 'data-product-name' => htmlspecialchars(json_encode($record->getTranslations('name')), ENT_QUOTES, 'UTF-8'),
- 'data-product-code' => $record->code ?: '',
- 'data-filename' => $coverMedia ? $coverMedia->file_name : '',
- 'onclick' => 'event.stopPropagation(); return false;',
- ];
- }),
+ return $images->map(fn ($media) => $media->getUrl())->toArray();
+ })
+ ->title(fn (Product $record) => "{$record->name} - Product Images")
+ ->link(fn (Product $record) => ProductResource::getUrl('edit', ['record' => $record])),
TextColumn::make('name')
->toggleable(false),
@@ -612,7 +601,7 @@ public static function table(Table $table): Table
->badge()
->getStateUsing(function (Product $record) {
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$status = null;
@@ -633,7 +622,7 @@ public static function table(Table $table): Table
})
->color(function (Product $record) {
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$status = null;
if ($record->relationLoaded('productData')) {
@@ -649,7 +638,7 @@ public static function table(Table $table): Table
})
->extraAttributes(function (Product $record) {
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$status = null;
if ($record->relationLoaded('productData')) {
@@ -687,7 +676,7 @@ public static function table(Table $table): Table
->limit(3)
->toggleable()
->getStateUsing(function (Product $record) {
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key', 'site_id');
if ($currentTenant) {
@@ -759,7 +748,7 @@ public static function table(Table $table): Table
->options(function () {
$query = ProductStatus::query();
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
if ($tenantFK && $currentTenant) {
$query->where($tenantFK, $currentTenant->id);
}
@@ -776,7 +765,7 @@ public static function table(Table $table): Table
return;
}
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$query->whereHas('productData', function ($q) use ($selected, $tenantFK, $currentTenant) {
if ($tenantFK && $currentTenant) {
$q->where($tenantFK, $currentTenant->id);
@@ -794,7 +783,7 @@ public static function table(Table $table): Table
return;
}
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$query->whereHas('productData', function ($q) use ($selected, $tenantFK, $currentTenant) {
if ($tenantFK && $currentTenant) {
$q->where($tenantFK, $currentTenant->id);
@@ -807,7 +796,7 @@ public static function table(Table $table): Table
->multiple()
->options(function () {
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$query = \Eclipse\Catalogue\Models\ProductType::query();
@@ -854,7 +843,7 @@ public static function table(Table $table): Table
->label('Groups')
->multiple()
->relationship('groups', 'name', function ($query) {
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key', 'site_id');
if ($currentTenant) {
return $query->where($tenantFK, $currentTenant->id);
@@ -867,7 +856,7 @@ public static function table(Table $table): Table
->queries(
true: function (Builder $query) {
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
return $query->whereHas('productData', function ($q) use ($tenantFK, $currentTenant) {
$q->where('is_active', true);
@@ -878,7 +867,7 @@ public static function table(Table $table): Table
},
false: function (Builder $query) {
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
return $query->whereHas('productData', function ($q) use ($tenantFK, $currentTenant) {
$q->where('is_active', false);
@@ -987,7 +976,7 @@ public static function getEloquentQuery(): Builder
]);
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
- $currentTenant = \Filament\Facades\Filament::getTenant();
+ $currentTenant = Filament::getTenant();
if ($tenantFK && $currentTenant) {
$query->with(['productData' => function ($q) use ($tenantFK, $currentTenant) {
@@ -1034,13 +1023,6 @@ public static function getGlobalSearchEloquentQuery(): Builder
->with(['customPropertyValues.property']);
}
- protected static function getPlaceholderImageUrl(): string
- {
- $svg = view('eclipse-catalogue::components.placeholder-image')->render();
-
- return 'data:image/svg+xml;base64,'.base64_encode($svg);
- }
-
public static function getPermissionPrefixes(): array
{
return [
@@ -1059,7 +1041,17 @@ public static function getPermissionPrefixes(): array
protected static function getCustomPropertyColumns(): array
{
- $customProperties = Property::where('type', 'custom')->get();
+ try {
+ // Check if the type column exists before querying
+ $customProperties = Property::where('type', PropertyType::CUSTOM->value)->get();
+ } catch (\Illuminate\Database\QueryException $e) {
+ // If type column doesn't exist, return empty array
+ if (str_contains($e->getMessage(), "Unknown column 'type'")) {
+ return [];
+ }
+ throw $e;
+ }
+
$columns = [];
foreach ($customProperties as $property) {
@@ -1094,10 +1086,19 @@ protected static function getCustomPropertyColumns(): array
protected static function getCustomPropertyConstraints(): array
{
$constraints = [];
- $customProperties = Property::where('is_active', true)
- ->where('type', 'custom')
- ->where('input_type', '!=', 'file')
- ->get();
+
+ try {
+ $customProperties = Property::where('is_active', true)
+ ->where('type', PropertyType::CUSTOM->value)
+ ->where('input_type', '!=', 'file')
+ ->get();
+ } catch (\Illuminate\Database\QueryException $e) {
+ // If type column doesn't exist, return empty array
+ if (str_contains($e->getMessage(), "Unknown column 'type'")) {
+ return [];
+ }
+ throw $e;
+ }
foreach ($customProperties as $property) {
$constraints[] = CustomPropertyConstraint::forProperty($property);
diff --git a/src/Filament/Resources/ProductResource/Pages/ListProducts.php b/src/Filament/Resources/ProductResource/Pages/ListProducts.php
index 2b41b61..6378eca 100644
--- a/src/Filament/Resources/ProductResource/Pages/ListProducts.php
+++ b/src/Filament/Resources/ProductResource/Pages/ListProducts.php
@@ -8,7 +8,6 @@
use Filament\Resources\Pages\ListRecords;
use Filament\Resources\Pages\ListRecords\Concerns\Translatable;
use Filament\Support\Enums\MaxWidth;
-use Illuminate\Contracts\View\View;
class ListProducts extends ListRecords
{
@@ -25,9 +24,4 @@ protected function getHeaderActions(): array
Actions\CreateAction::make(),
];
}
-
- public function getFooter(): ?View
- {
- return view('eclipse-catalogue::filament.resources.product-resource.pages.list-products-footer');
- }
}