diff --git a/app/Filament/Admin/Resources/FooterTemplates/Schemas/FooterTemplateForm.php b/app/Filament/Admin/Resources/FooterTemplates/Schemas/FooterTemplateForm.php index 8329278..fcb9058 100644 --- a/app/Filament/Admin/Resources/FooterTemplates/Schemas/FooterTemplateForm.php +++ b/app/Filament/Admin/Resources/FooterTemplates/Schemas/FooterTemplateForm.php @@ -6,6 +6,7 @@ use Filament\Forms\Components\CodeEditor; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\View; use Filament\Schemas\Schema; class FooterTemplateForm @@ -22,19 +23,31 @@ class FooterTemplateForm ->maxLength(255) ->columnSpanFull(), + // Preview Component + View::make('components.template-preview') + ->extraAttributes([ + 'data-type' => 'footer', + 'data-field-name' => 'html_content', + ]) + ->columnSpanFull(), + CodeEditor::make('html_content') ->label(__('footer-templates.field_html_content')) ->required() - //->lineNumbers() + ->live(onBlur: false) // Real-time updates ->columnSpanFull() - ->helperText(__('footer-templates.field_html_content_help')), + ->helperText(__('footer-templates.field_html_content_help')) + ->extraAttributes([ + 'style' => 'min-height: 400px;', + 'data-field-name' => 'html_content', + ]), Toggle::make('is_active') ->label(__('footer-templates.field_is_active')) ->default(true) ->inline(false), ]) - ->columns(2), + ->columnSpanFull(), ]); } } diff --git a/app/Filament/Admin/Resources/HeaderTemplates/Schemas/HeaderTemplateForm.php b/app/Filament/Admin/Resources/HeaderTemplates/Schemas/HeaderTemplateForm.php index 48a670a..50caa00 100644 --- a/app/Filament/Admin/Resources/HeaderTemplates/Schemas/HeaderTemplateForm.php +++ b/app/Filament/Admin/Resources/HeaderTemplates/Schemas/HeaderTemplateForm.php @@ -6,6 +6,7 @@ use Filament\Forms\Components\CodeEditor; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\View; use Filament\Schemas\Schema; class HeaderTemplateForm @@ -22,19 +23,31 @@ class HeaderTemplateForm ->maxLength(255) ->columnSpanFull(), + // Preview Component + View::make('components.template-preview') + ->extraAttributes([ + 'data-type' => 'header', + 'data-field-name' => 'html_content', + ]) + ->columnSpanFull(), + CodeEditor::make('html_content') ->label(__('header-templates.field_html_content')) ->required() - //->lineNumbers() + ->live(onBlur: false) // Real-time updates ->columnSpanFull() - ->helperText(__('header-templates.field_html_content_help')), + ->helperText(__('header-templates.field_html_content_help')) + ->extraAttributes([ + 'style' => 'min-height: 400px;', + 'data-field-name' => 'html_content', + ]), Toggle::make('is_active') ->label(__('header-templates.field_is_active')) ->default(true) ->inline(false), ]) - ->columns(2), + ->columnSpanFull(), ]); } } diff --git a/app/Filament/Admin/Resources/SectionTemplates/Schemas/SectionTemplateForm.php b/app/Filament/Admin/Resources/SectionTemplates/Schemas/SectionTemplateForm.php index ed7e00b..fd98fbe 100644 --- a/app/Filament/Admin/Resources/SectionTemplates/Schemas/SectionTemplateForm.php +++ b/app/Filament/Admin/Resources/SectionTemplates/Schemas/SectionTemplateForm.php @@ -6,6 +6,7 @@ use Filament\Forms\Components\CodeEditor; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\View; use Filament\Schemas\Schema; class SectionTemplateForm @@ -22,19 +23,31 @@ class SectionTemplateForm ->maxLength(255) ->columnSpanFull(), + // Preview Component + View::make('components.template-preview') + ->extraAttributes([ + 'data-type' => 'section', + 'data-field-name' => 'html_content', + ]) + ->columnSpanFull(), + CodeEditor::make('html_content') ->label(__('section-templates.field_html_content')) ->required() - //->lineNumbers() + ->live(onBlur: false) // Real-time updates ->columnSpanFull() - ->helperText(__('section-templates.field_html_content_help')), + ->helperText(__('section-templates.field_html_content_help')) + ->extraAttributes([ + 'style' => 'min-height: 400px;', + 'data-field-name' => 'html_content', + ]), Toggle::make('is_active') ->label(__('section-templates.field_is_active')) ->default(true) ->inline(false), ]) - ->columns(2), + ->columnSpanFull(), ]); } } diff --git a/app/Http/Controllers/TemplatePreviewController.php b/app/Http/Controllers/TemplatePreviewController.php new file mode 100644 index 0000000..476303f --- /dev/null +++ b/app/Http/Controllers/TemplatePreviewController.php @@ -0,0 +1,32 @@ +input('content', ''); + $type = $request->input('type', 'section'); // header, footer, section + + // Validate type + if (!in_array($type, ['header', 'footer', 'section'])) { + $type = 'section'; + } + + $html = TemplatePreviewService::getPreviewHtml($content, $type); + + return response($html) + ->header('Content-Type', 'text/html; charset=utf-8'); + } +} + diff --git a/app/Services/TemplatePreviewService.php b/app/Services/TemplatePreviewService.php new file mode 100644 index 0000000..bb57087 --- /dev/null +++ b/app/Services/TemplatePreviewService.php @@ -0,0 +1,150 @@ + $settingKey) { + if (str_starts_with($assetKey, 'css_')) { + $setting = Setting::get($settingKey); + if ($setting) { + $configKey = str_replace('css_', '', $assetKey); + $config[$configKey] = $setting; + } + } + } + } + + return $config; + } + + /** + * Get all JavaScript assets for preview + * + * @return array + */ + public static function getJsAssets(): array + { + $config = config('template-preview.js', []); + + if (config('template-preview.use_settings_override', false)) { + $settingsKeys = config('template-preview.settings_keys', []); + + foreach ($settingsKeys as $assetKey => $settingKey) { + if (str_starts_with($assetKey, 'js_')) { + $setting = Setting::get($settingKey); + if ($setting) { + $configKey = str_replace('js_', '', $assetKey); + $config[$configKey] = $setting; + } + } + } + } + + return $config; + } + + /** + * Get formatted CSS link tags + * + * @return string + */ + public static function getCssLinks(): string + { + $assets = self::getCssAssets(); + $html = ''; + + foreach ($assets as $key => $path) { + if ($key === 'fonts') { + // Preload for fonts + $html .= sprintf( + '' . "\n", + asset($path) + ); + } else { + $html .= sprintf( + '' . "\n", + asset($path) + ); + } + } + + return $html; + } + + /** + * Get formatted JavaScript script tags + * + * @return string + */ + public static function getJsScripts(): string + { + $assets = self::getJsAssets(); + $html = ''; + + foreach ($assets as $path) { + $html .= sprintf( + '' . "\n", + asset($path) + ); + } + + return $html; + } + + /** + * Get full HTML structure for preview + * + * @param string $content The template HTML content + * @param string $type The template type: 'header', 'footer', or 'section' + * @return string + */ + public static function getPreviewHtml(string $content, string $type = 'section'): string + { + $cssLinks = self::getCssLinks(); + $jsScripts = self::getJsScripts(); + $meta = config('template-preview.meta', []); + + $viewport = $meta['viewport'] ?? 'width=device-width, initial-scale=1'; + $charset = $meta['charset'] ?? 'utf-8'; + + // Wrap content based on type + $bodyContent = match($type) { + 'header' => $content, + 'footer' => $content, + 'section' => '
' . $content . '
', + default => $content, + }; + + return << + + + + + Template Preview + {$cssLinks} + + + {$bodyContent} + {$jsScripts} + + +HTML; + } +} + diff --git a/config/template-preview.php b/config/template-preview.php new file mode 100644 index 0000000..73c5b2c --- /dev/null +++ b/config/template-preview.php @@ -0,0 +1,54 @@ + [ + 'style' => 'html/style.css', + 'unicons' => 'assets/fonts/unicons/unicons.css', + 'plugins' => 'assets/css/plugins.css', + 'colors' => 'assets/css/colors/grape.css', + 'fonts' => 'assets/css/fonts/urbanist.css', + ], + + // JavaScript Assets + 'js' => [ + 'plugins' => 'assets/js/plugins.js', + 'theme' => 'assets/js/theme.js', + ], + + // Additional meta tags and head content + 'meta' => [ + 'viewport' => 'width=device-width, initial-scale=1', + 'charset' => 'utf-8', + ], + + // Whether to load assets from Settings table (overrides config) + 'use_settings_override' => false, + + // Settings keys for asset paths (if use_settings_override is true) + 'settings_keys' => [ + 'css_style' => 'template_preview_css_style', + 'css_unicons' => 'template_preview_css_unicons', + 'css_plugins' => 'template_preview_css_plugins', + 'css_colors' => 'template_preview_css_colors', + 'css_fonts' => 'template_preview_css_fonts', + 'js_plugins' => 'template_preview_js_plugins', + 'js_theme' => 'template_preview_js_theme', + ], +]; + diff --git a/resources/views/components/template-preview.blade.php b/resources/views/components/template-preview.blade.php new file mode 100644 index 0000000..39c920f --- /dev/null +++ b/resources/views/components/template-preview.blade.php @@ -0,0 +1,288 @@ +@php + $previewUrl = route('template.preview'); + // Get type and fieldName from component attributes or defaults + $type = $attributes->get('data-type') ?? 'section'; + $fieldName = $attributes->get('data-field-name') ?? 'html_content'; +@endphp + +
+
+ +
+ +
+ +
+
+ + + + +

+ Yükleniyor... + Önizleme için içerik girin +

+
+
+ + + +
+ +

+ {{ __('Önizleme gerçek zamanlı olarak güncellenir') }} +

+
+ +@push('scripts') + +@endpush + diff --git a/routes/web.php b/routes/web.php index 81d1cb8..2766a28 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,6 +3,7 @@ use Illuminate\Support\Facades\Route; use App\Http\Controllers\PageController; use App\Http\Controllers\BlogController; +use App\Http\Controllers\TemplatePreviewController; use App\Models\Page; // Debug Route - Veritabanı kontrolü @@ -60,5 +61,10 @@ Route::get('/', [PageController::class, 'index'])->name('homepage'); Route::get('/blog', [BlogController::class, 'index'])->name('blog.index'); Route::get('/blog/{slug}', [BlogController::class, 'show'])->name('blog.show'); +// Template Preview (admin panel için) +Route::post('/admin/template-preview', [TemplatePreviewController::class, 'preview']) + ->middleware(['auth']) + ->name('template.preview'); + // Pages (en sonda olmalı - catch-all) Route::get('/{slug}', [PageController::class, 'show'])->name('page.show');