Enhance Template Import and Preview Functionality: Updated the ImportHtmlTemplates command to improve asset path handling by moving files to storage and updating HTML asset paths. Added a preview action in SectionTemplatesTable for better template management, along with a new Blade view for rendering previews. Adjusted route for template preview to accept any request method for flexibility.
This commit is contained in:
@@ -7,6 +7,7 @@ use App\Models\HeaderTemplate;
|
|||||||
use App\Models\SectionTemplate;
|
use App\Models\SectionTemplate;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
use DOMDocument;
|
use DOMDocument;
|
||||||
use DOMXPath;
|
use DOMXPath;
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
@@ -313,14 +314,53 @@ class ImportHtmlTemplates extends Command
|
|||||||
|
|
||||||
protected function fixAssetPath($path)
|
protected function fixAssetPath($path)
|
||||||
{
|
{
|
||||||
|
// Eğer URL ise elleme
|
||||||
|
if (str_starts_with($path, 'http://') || str_starts_with($path, 'https://')) {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assets klasöründeki dosyaları storage'a taşı
|
||||||
if (str_starts_with($path, 'assets/')) {
|
if (str_starts_with($path, 'assets/')) {
|
||||||
|
$sourcePath = public_path('html/' . $path);
|
||||||
|
|
||||||
|
if (File::exists($sourcePath)) {
|
||||||
|
// Dosya adını ve klasörünü belirle
|
||||||
|
$fileName = basename($path);
|
||||||
|
// Çakışmayı önlemek için orijinal klasör yapısını korumaya çalışabiliriz
|
||||||
|
// veya basitçe 'templates/imported' altına atabiliriz.
|
||||||
|
|
||||||
|
// Storage hedef yolu: templates/imported/filename.ext
|
||||||
|
$targetDir = 'templates/imported';
|
||||||
|
$targetPath = $targetDir . '/' . $fileName;
|
||||||
|
|
||||||
|
// Eğer storage'da bu dosya yoksa kopyala
|
||||||
|
if (!Storage::disk('public')->exists($targetPath)) {
|
||||||
|
Storage::disk('public')->put($targetPath, File::get($sourcePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Veritabanına kaydedilecek değer: templates/imported/filename.ext
|
||||||
|
// Bu değer Filament FileUpload tarafından 'public' diskinde otomatik olarak bulunur.
|
||||||
|
return $targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dosya bulunamadıysa eski usul devam et
|
||||||
return '/html/' . $path;
|
return '/html/' . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function fixAssetPathInString($html)
|
protected function fixAssetPathInString($html)
|
||||||
{
|
{
|
||||||
|
// HTML string içindeki asset pathlerini güncelle
|
||||||
|
// Burada da aynı mantıkla storage pathlerine çevirebilirdik ama
|
||||||
|
// string içindeki pathleri tek tek bulup kopyalamak zor ve performanssız olabilir.
|
||||||
|
// Şimdilik sadece URL'leri düzeltiyoruz, import edilen resimler zaten processNode kısmında hallediliyor.
|
||||||
|
// Background-image gibi CSS içindeki pathler için burası önemli.
|
||||||
|
|
||||||
|
// CSS içindeki url('assets/...') kısımlarını yakalamak için daha genel bir yaklaşım
|
||||||
|
// Ancak processNode zaten img taglerini hallettiği için burası sadece kalanlar için.
|
||||||
|
|
||||||
$html = str_replace('src="assets/', 'src="/html/assets/', $html);
|
$html = str_replace('src="assets/', 'src="/html/assets/', $html);
|
||||||
$html = str_replace('href="assets/', 'href="/html/assets/', $html);
|
$html = str_replace('href="assets/', 'href="/html/assets/', $html);
|
||||||
$html = str_replace("src='assets/", "src='/html/assets/", $html);
|
$html = str_replace("src='assets/", "src='/html/assets/", $html);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use Filament\Actions\EditAction;
|
|||||||
use Filament\Actions\ForceDeleteBulkAction;
|
use Filament\Actions\ForceDeleteBulkAction;
|
||||||
use Filament\Actions\RestoreBulkAction;
|
use Filament\Actions\RestoreBulkAction;
|
||||||
use Filament\Actions\ViewAction;
|
use Filament\Actions\ViewAction;
|
||||||
|
use Filament\Actions\Action;
|
||||||
use Filament\Tables\Columns\IconColumn;
|
use Filament\Tables\Columns\IconColumn;
|
||||||
use Filament\Tables\Columns\TextColumn;
|
use Filament\Tables\Columns\TextColumn;
|
||||||
use Filament\Tables\Filters\TrashedFilter;
|
use Filament\Tables\Filters\TrashedFilter;
|
||||||
@@ -51,6 +52,13 @@ class SectionTemplatesTable
|
|||||||
TrashedFilter::make(),
|
TrashedFilter::make(),
|
||||||
])
|
])
|
||||||
->recordActions([
|
->recordActions([
|
||||||
|
Action::make('preview')
|
||||||
|
->label(__('section-templates.action_preview'))
|
||||||
|
->icon('heroicon-o-eye')
|
||||||
|
->modalContent(fn ($record) => view('filament.admin.resources.section-templates.preview', ['record' => $record]))
|
||||||
|
->modalSubmitAction(false)
|
||||||
|
->modalCancelAction(false)
|
||||||
|
->modalWidth('7xl'),
|
||||||
ViewAction::make(),
|
ViewAction::make(),
|
||||||
EditAction::make(),
|
EditAction::make(),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -314,8 +314,9 @@ class TemplateService
|
|||||||
* @param string $html HTML content with placeholders
|
* @param string $html HTML content with placeholders
|
||||||
* @param array $data Data array for placeholders
|
* @param array $data Data array for placeholders
|
||||||
* @param Model|null $model Optional model instance (Page, Blog, etc.) for dynamic data
|
* @param Model|null $model Optional model instance (Page, Blog, etc.) for dynamic data
|
||||||
|
* @param array $defaultData Optional default data for fallback
|
||||||
*/
|
*/
|
||||||
public static function replacePlaceholders(string $html, array $data, ?Model $model = null): string
|
public static function replacePlaceholders(string $html, array $data, ?Model $model = null, array $defaultData = []): string
|
||||||
{
|
{
|
||||||
// Handle special {page.content} placeholder - Sayfa/model içeriğini gösterir
|
// Handle special {page.content} placeholder - Sayfa/model içeriğini gösterir
|
||||||
if (str_contains($html, '{page.content}')) {
|
if (str_contains($html, '{page.content}')) {
|
||||||
@@ -564,6 +565,11 @@ class TemplateService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5. Fallback to default data
|
||||||
|
if (($value === null || $value === '') && isset($defaultData[$placeholder])) {
|
||||||
|
$value = $defaultData[$placeholder];
|
||||||
|
}
|
||||||
|
|
||||||
// Handle different value types
|
// Handle different value types
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
// Handle arrays (e.g., multiple images)
|
// Handle arrays (e.g., multiple images)
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="w-full flex flex-col" style="height: 600px;">
|
||||||
|
<div class="flex-1 w-full relative bg-white border rounded-lg overflow-hidden">
|
||||||
|
<iframe
|
||||||
|
src="{{ route('template.preview', ['type' => 'section', 'record_id' => $record->id]) }}"
|
||||||
|
class="w-full h-full absolute inset-0 border-0"
|
||||||
|
style="width: 100%; height: 100%;"
|
||||||
|
title="Preview"
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
+1
-1
@@ -77,7 +77,7 @@ Route::get('/blog/{slug}', [BlogController::class, 'show'])->name('blog.show');
|
|||||||
Route::post('/blog/{slug}/comment', [BlogController::class, 'storeComment'])->name('blog.comment.store');
|
Route::post('/blog/{slug}/comment', [BlogController::class, 'storeComment'])->name('blog.comment.store');
|
||||||
|
|
||||||
// Template Preview (admin panel için)
|
// Template Preview (admin panel için)
|
||||||
Route::post('/admin/template-preview', [TemplatePreviewController::class, 'preview'])
|
Route::any('/admin/template-preview', [TemplatePreviewController::class, 'preview'])
|
||||||
->middleware(['auth'])
|
->middleware(['auth'])
|
||||||
->name('template.preview');
|
->name('template.preview');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user