2026-01-02 13:58:06 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Filament\Resources\Entries\Schemas;
|
|
|
|
|
|
2026-01-02 18:59:24 +00:00
|
|
|
use Filament\Actions\Action;
|
2026-01-02 13:58:06 +00:00
|
|
|
use Filament\Forms\Components\DatePicker;
|
|
|
|
|
use Filament\Forms\Components\RichEditor;
|
2026-01-02 18:59:24 +00:00
|
|
|
use Filament\Forms\Components\Select;
|
2026-01-03 13:22:14 +00:00
|
|
|
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
|
2026-01-02 13:58:06 +00:00
|
|
|
use Filament\Forms\Components\Textarea;
|
2026-01-02 18:59:24 +00:00
|
|
|
use Filament\Forms\Components\TextInput;
|
2026-01-02 13:58:06 +00:00
|
|
|
use Filament\Forms\Components\Toggle;
|
|
|
|
|
use Filament\Schemas\Schema;
|
2026-01-03 14:25:23 +00:00
|
|
|
use Illuminate\Support\Facades\Storage;
|
2026-01-02 13:58:06 +00:00
|
|
|
use Illuminate\Support\Str;
|
2026-01-02 18:59:24 +00:00
|
|
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
2026-01-02 13:58:06 +00:00
|
|
|
|
|
|
|
|
class EntryForm
|
|
|
|
|
{
|
|
|
|
|
public static function configure(Schema $schema): Schema
|
|
|
|
|
{
|
|
|
|
|
return $schema
|
|
|
|
|
->components([
|
|
|
|
|
TextInput::make('title')
|
|
|
|
|
->required()
|
2026-01-02 18:59:24 +00:00
|
|
|
->live(onBlur: true)
|
2026-01-02 13:58:06 +00:00
|
|
|
->afterStateUpdated(function ($state, $set): void {
|
|
|
|
|
$set('slug', Str::slug((string) $state));
|
|
|
|
|
}),
|
|
|
|
|
TextInput::make('slug')
|
|
|
|
|
->required()
|
2026-01-02 18:59:24 +00:00
|
|
|
->dehydrated()
|
|
|
|
|
->readOnly(),
|
2026-01-02 13:58:06 +00:00
|
|
|
Textarea::make('description')
|
|
|
|
|
->columnSpanFull(),
|
2026-01-03 13:22:14 +00:00
|
|
|
SpatieMediaLibraryFileUpload::make('featured_image')
|
|
|
|
|
->collection('featured-image')
|
|
|
|
|
->image()
|
|
|
|
|
->imageEditor()
|
2026-01-03 14:52:52 +00:00
|
|
|
->disk('public')
|
|
|
|
|
->visibility('public')
|
2026-01-03 13:35:38 +00:00
|
|
|
->columnSpanFull()
|
|
|
|
|
->hintAction(
|
|
|
|
|
Action::make('featured_picker')
|
|
|
|
|
->label('Pick from Gallery')
|
|
|
|
|
->icon('heroicon-m-photo')
|
|
|
|
|
->schema([
|
|
|
|
|
Select::make('image_id')
|
|
|
|
|
->label('Select an existing image')
|
|
|
|
|
->allowHtml()
|
|
|
|
|
->options(function () {
|
|
|
|
|
return Media::latest()
|
|
|
|
|
->get()
|
|
|
|
|
->mapWithKeys(function (Media $item) {
|
|
|
|
|
$url = $item->getUrl();
|
|
|
|
|
|
|
|
|
|
$fileName = e($item->file_name);
|
|
|
|
|
$name = e($item->name ?? '');
|
|
|
|
|
|
|
|
|
|
$html = "<div class='flex items-center gap-2 w-full'>".
|
|
|
|
|
"<img src=\"{$url}\" class=\"rounded\" style=\"max-width:200px;max-height:200px;object-fit:cover;width:auto;height:auto;\" alt=\"{$fileName}\"/>".
|
|
|
|
|
"<span class=\"ml-2 truncate\">{$name} — {$fileName}</span></div>";
|
|
|
|
|
|
|
|
|
|
return [$item->id => $html];
|
|
|
|
|
})->toArray();
|
|
|
|
|
})
|
|
|
|
|
->searchable()
|
|
|
|
|
->required(),
|
|
|
|
|
])
|
|
|
|
|
->action(function (array $data, SpatieMediaLibraryFileUpload $component) {
|
|
|
|
|
$record = $component->getRecord();
|
|
|
|
|
|
2026-01-03 14:25:23 +00:00
|
|
|
if (!$record) {
|
|
|
|
|
\Filament\Notifications\Notification::make()
|
|
|
|
|
->warning()
|
|
|
|
|
->title('Save the entry first')
|
|
|
|
|
->send();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($mediaItem = Media::find($data['image_id'])) {
|
|
|
|
|
// Clear existing featured image
|
2026-01-03 13:35:38 +00:00
|
|
|
$record->clearMediaCollection('featured-image');
|
|
|
|
|
|
2026-01-03 14:25:23 +00:00
|
|
|
// Download from the full URL and add as new media
|
|
|
|
|
$fullUrl = url($mediaItem->getUrl());
|
2026-01-03 13:35:38 +00:00
|
|
|
|
2026-01-03 14:25:23 +00:00
|
|
|
$newMedia = $record->addMediaFromUrl($fullUrl)
|
2026-01-03 13:35:38 +00:00
|
|
|
->usingName($mediaItem->name ?: $mediaItem->file_name)
|
|
|
|
|
->usingFileName($mediaItem->file_name)
|
2026-01-03 14:52:52 +00:00
|
|
|
->toMediaCollection('featured-image', 'public');
|
2026-01-03 13:35:38 +00:00
|
|
|
|
2026-01-03 14:25:23 +00:00
|
|
|
// Update component state
|
|
|
|
|
$component->state([$newMedia->uuid]);
|
|
|
|
|
|
|
|
|
|
\Filament\Notifications\Notification::make()
|
|
|
|
|
->success()
|
|
|
|
|
->title('Featured image set')
|
|
|
|
|
->send();
|
2026-01-03 13:35:38 +00:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
),
|
2026-01-02 13:58:06 +00:00
|
|
|
Toggle::make('is_published')
|
|
|
|
|
->required(),
|
|
|
|
|
Toggle::make('is_featured')
|
|
|
|
|
->required(),
|
|
|
|
|
DatePicker::make('published_at'),
|
|
|
|
|
RichEditor::make('content')
|
2026-01-02 18:59:24 +00:00
|
|
|
->columnSpanFull()
|
|
|
|
|
->hintAction(
|
|
|
|
|
Action::make('picker')
|
|
|
|
|
->label('Gallery Picker')
|
|
|
|
|
->icon('heroicon-m-photo')
|
|
|
|
|
->schema([
|
|
|
|
|
Select::make('image_url')
|
|
|
|
|
->label('Select an existing image')
|
|
|
|
|
->allowHtml()
|
|
|
|
|
->options(function () {
|
|
|
|
|
// We must 'get' the collection first so we can call getUrl()
|
|
|
|
|
// because 'url' is not a column in the Spatie database table.
|
|
|
|
|
return Media::latest()
|
|
|
|
|
->get()
|
|
|
|
|
->mapWithKeys(function (Media $item) {
|
|
|
|
|
$url = $item->getUrl();
|
|
|
|
|
|
|
|
|
|
$fileName = e($item->file_name);
|
|
|
|
|
$name = e($item->name ?? '');
|
|
|
|
|
|
|
|
|
|
$html = "<div class='flex items-center gap-2 w-full'>".
|
|
|
|
|
"<img src=\"{$url}\" class=\"rounded\" style=\"max-width:200px;max-height:200px;object-fit:cover;width:auto;height:auto;\" alt=\"{$fileName}\"/>".
|
|
|
|
|
"<span class=\"ml-2 truncate\">{$name} — {$fileName}</span></div>";
|
|
|
|
|
|
|
|
|
|
return [$url => $html];
|
|
|
|
|
})->toArray();
|
|
|
|
|
})
|
|
|
|
|
->searchable()
|
|
|
|
|
->required(),
|
|
|
|
|
])
|
|
|
|
|
->action(function (array $data, RichEditor $component) {
|
|
|
|
|
// We dispatch the URL to the browser to be inserted into TipTap
|
|
|
|
|
$component->getLivewire()->dispatch('insert-editor-content', [
|
|
|
|
|
'statePath' => $component->getStatePath(),
|
|
|
|
|
'html' => "<img src='{$data['image_url']}' alt=''>",
|
|
|
|
|
]);
|
|
|
|
|
})
|
|
|
|
|
),
|
|
|
|
|
|
2026-01-02 13:58:06 +00:00
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|