diff --git a/app/Filament/Admin/Resources/SiteTranslations/Pages/ListSiteTranslations.php b/app/Filament/Admin/Resources/SiteTranslations/Pages/ListSiteTranslations.php index 3a0324c..d0b19d4 100644 --- a/app/Filament/Admin/Resources/SiteTranslations/Pages/ListSiteTranslations.php +++ b/app/Filament/Admin/Resources/SiteTranslations/Pages/ListSiteTranslations.php @@ -5,17 +5,54 @@ namespace App\Filament\Admin\Resources\SiteTranslations\Pages; use App\Filament\Admin\Resources\SiteTranslations\SiteTranslationResource; use Filament\Actions\CreateAction; use Filament\Resources\Pages\ListRecords; +use Filament\Actions\Action; +use Illuminate\Contracts\View\View; class ListSiteTranslations extends ListRecords { protected static string $resource = SiteTranslationResource::class; + public bool $useDataGrid = false; + + public function mount(): void + { + parent::mount(); + + // Session'dan görünüm tercihini al, yoksa varsayılan olarak false (eski görünüm) + $this->useDataGrid = session('site_translations_use_datagrid', false); + } + protected function getHeaderActions(): array { return [ - CreateAction::make(), + Action::make('toggleView') + ->label(fn() => $this->useDataGrid ? 'Tablo Görünümü' : 'DataGrid Görünümü') + ->icon(fn() => $this->useDataGrid ? 'heroicon-o-table-cells' : 'heroicon-o-squares-2x2') + ->color('gray') + ->action(function () { + $this->useDataGrid = !$this->useDataGrid; + session(['site_translations_use_datagrid' => $this->useDataGrid]); + + // Sayfayı yenile ki getContent() yeniden çağrılsın + return redirect()->to($this->getResource()::getUrl('index')); + }), + CreateAction::make() + ->visible(fn() => !$this->useDataGrid), // Sadece eski görünümde göster ]; } + + public function getContent(): View + { + // Session'dan direkt oku ki her render'da güncel değeri alsın + $useDataGrid = session('site_translations_use_datagrid', false); + + if ($useDataGrid) { + return view('filament.admin.resources.site-translations.datagrid'); + } + + // Eski Filament table görünümü + return parent::getContent(); + } } diff --git a/app/Http/Controllers/Api/SiteTranslationController.php b/app/Http/Controllers/Api/SiteTranslationController.php new file mode 100644 index 0000000..7177516 --- /dev/null +++ b/app/Http/Controllers/Api/SiteTranslationController.php @@ -0,0 +1,292 @@ +has('search')) { + $search = $request->get('search'); + $query->where(function ($q) use ($search) { + $q->where('key', 'like', "%{$search}%") + ->orWhereRaw("JSON_SEARCH(translations, 'one', ?, NULL, '$[*]') IS NOT NULL", ["%{$search}%"]); + }); + } + + // Sorting + $sortField = $request->get('sort', 'id'); + $sortOrder = $request->get('order', 'desc'); + $query->orderBy($sortField, $sortOrder); + + // Pagination + $page = $request->get('page', 1); + $pageSize = $request->get('pageSize', 20); + + $totalCount = $query->count(); + $items = $query->skip(($page - 1) * $pageSize)->take($pageSize)->get(); + + // Format data for DataGrid + $data = $items->map(function ($item) { + $formatted = [ + 'id' => $item->id, + 'key' => $item->key, + 'hash' => $item->hash, + 'created_at' => $item->created_at?->toDateTimeString(), + 'updated_at' => $item->updated_at?->toDateTimeString(), + ]; + + // Add translation fields for each active language + $languages = Language::where('is_active', true)->get(); + $translations = $item->translations ?? []; + + foreach ($languages as $language) { + $formatted[$language->code] = $translations[$language->code] ?? ''; + } + + return $formatted; + }); + + return response()->json([ + 'data' => $data, + 'totalCount' => $totalCount, + ]); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request): JsonResponse + { + $validator = Validator::make($request->all(), [ + 'key' => 'required|string|max:500', + ]); + + if ($validator->fails()) { + return response()->json([ + 'success' => false, + 'errors' => $validator->errors(), + ], 422); + } + + $hash = md5($request->key); + + // Check if translation already exists + $exists = SiteTranslation::where('hash', $hash)->first(); + if ($exists) { + return response()->json([ + 'success' => false, + 'message' => 'Bu key zaten mevcut.', + ], 409); + } + + $languages = Language::where('is_active', true)->get(); + $translations = []; + + foreach ($languages as $language) { + if ($request->has($language->code)) { + $translations[$language->code] = $request->get($language->code, ''); + } + } + + $translation = SiteTranslation::create([ + 'hash' => $hash, + 'key' => $request->key, + 'translations' => $translations, + ]); + + Cache::forget("site_translation_{$hash}"); + + return response()->json([ + 'success' => true, + 'data' => $translation->load('translations'), + 'message' => 'Çeviri başarıyla oluşturuldu.', + ], 201); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, $id): JsonResponse + { + $translation = SiteTranslation::findOrFail($id); + + $validator = Validator::make($request->all(), [ + 'key' => 'sometimes|required|string|max:500', + ]); + + if ($validator->fails()) { + return response()->json([ + 'success' => false, + 'errors' => $validator->errors(), + ], 422); + } + + $languages = Language::where('is_active', true)->get(); + $translations = $translation->translations ?? []; + + // Update translations + foreach ($languages as $language) { + if ($request->has($language->code)) { + $translations[$language->code] = $request->get($language->code, ''); + } + } + + // Update key if provided + if ($request->has('key') && $request->key !== $translation->key) { + $translation->key = $request->key; + $translation->hash = md5($request->key); + } + + $translation->translations = $translations; + $translation->save(); + + Cache::forget("site_translation_{$translation->hash}"); + + return response()->json([ + 'success' => true, + 'data' => $translation->fresh(), + 'message' => 'Çeviri başarıyla güncellendi.', + ]); + } + + /** + * Batch update multiple resources. + */ + public function batchUpdate(Request $request): JsonResponse + { + $validator = Validator::make($request->all(), [ + 'changes' => 'required|array', + ]); + + if ($validator->fails()) { + return response()->json([ + 'success' => false, + 'errors' => $validator->fails(), + ], 422); + } + + $changes = $request->get('changes', []); + $updated = []; + $errors = []; + + foreach ($changes as $change) { + try { + // ID can be in 'key' field (integer) or directly in 'key' field + $id = is_numeric($change['key'] ?? null) + ? (int)$change['key'] + : ($change['key']['id'] ?? null); + + if (!$id) { + $errors[] = 'ID bulunamadı.'; + continue; + } + + $translation = SiteTranslation::find($id); + if (!$translation) { + $errors[] = "ID {$id} için kayıt bulunamadı."; + continue; + } + + $data = $change['data'] ?? []; + $languages = Language::where('is_active', true)->get(); + $translations = $translation->translations ?? []; + + // Update translations + foreach ($languages as $language) { + if (isset($data[$language->code])) { + $translations[$language->code] = $data[$language->code]; + } + } + + // Update key if provided + if (isset($data['key']) && $data['key'] !== $translation->key) { + $translation->key = $data['key']; + $translation->hash = md5($data['key']); + } + + $translation->translations = $translations; + $translation->save(); + + Cache::forget("site_translation_{$translation->hash}"); + + $updated[] = $translation->id; + } catch (\Exception $e) { + $id = is_numeric($change['key'] ?? null) + ? (int)$change['key'] + : ($change['key']['id'] ?? 'unknown'); + $errors[] = "ID {$id} için hata: " . $e->getMessage(); + } + } + + return response()->json([ + 'success' => count($errors) === 0, + 'updated' => $updated, + 'errors' => $errors, + 'message' => count($updated) . ' kayıt güncellendi.', + ]); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy($id): JsonResponse + { + $translation = SiteTranslation::findOrFail($id); + $hash = $translation->hash; + + $translation->delete(); + Cache::forget("site_translation_{$hash}"); + + return response()->json([ + 'success' => true, + 'message' => 'Çeviri başarıyla silindi.', + ]); + } + + /** + * Batch delete multiple resources. + */ + public function batchDestroy(Request $request): JsonResponse + { + $validator = Validator::make($request->all(), [ + 'ids' => 'required|array', + 'ids.*' => 'required|integer|exists:site_translations,id', + ]); + + if ($validator->fails()) { + return response()->json([ + 'success' => false, + 'errors' => $validator->errors(), + ], 422); + } + + $ids = $request->get('ids', []); + $translations = SiteTranslation::whereIn('id', $ids)->get(); + + foreach ($translations as $translation) { + Cache::forget("site_translation_{$translation->hash}"); + } + + SiteTranslation::whereIn('id', $ids)->delete(); + + return response()->json([ + 'success' => true, + 'message' => count($ids) . ' kayıt başarıyla silindi.', + ]); + } +} diff --git a/resources/views/filament/admin/resources/site-translations/datagrid.blade.php b/resources/views/filament/admin/resources/site-translations/datagrid.blade.php new file mode 100644 index 0000000..3219823 --- /dev/null +++ b/resources/views/filament/admin/resources/site-translations/datagrid.blade.php @@ -0,0 +1,389 @@ + + @php + $languages = \App\Models\Language::where('is_active', true)->get(); + $apiUrl = route('api.site-translations.index'); + $apiStoreUrl = route('api.site-translations.store'); + $apiUpdateUrl = route('api.site-translations.update', ['id' => '__ID__']); + $apiDeleteUrl = route('api.site-translations.destroy', ['id' => '__ID__']); + $apiBatchUpdateUrl = route('api.site-translations.batch-update'); + $apiBatchDeleteUrl = route('api.site-translations.batch-destroy'); + + // CSRF token + $csrfToken = csrf_token(); + @endphp + +
+
+

DataGrid yükleniyor...

+
+
+ + + + + + + +
diff --git a/routes/web.php b/routes/web.php index a4bcaab..2b6a596 100644 --- a/routes/web.php +++ b/routes/web.php @@ -4,6 +4,7 @@ use Illuminate\Support\Facades\Route; use App\Http\Controllers\PageController; use App\Http\Controllers\BlogController; use App\Http\Controllers\TemplatePreviewController; +use App\Http\Controllers\Api\SiteTranslationController; use App\Models\Page; // Debug Route - Veritabanı kontrolü @@ -85,6 +86,16 @@ Route::any('/admin/template-preview', [TemplatePreviewController::class, 'previe ->middleware(['auth']) ->name('template.preview'); +// Site Translations API (DevExtreme DataGrid için) +Route::prefix('admin/api')->middleware(['auth'])->group(function () { + Route::get('/site-translations', [SiteTranslationController::class, 'index'])->name('api.site-translations.index'); + Route::post('/site-translations', [SiteTranslationController::class, 'store'])->name('api.site-translations.store'); + Route::put('/site-translations/{id}', [SiteTranslationController::class, 'update'])->name('api.site-translations.update'); + Route::delete('/site-translations/{id}', [SiteTranslationController::class, 'destroy'])->name('api.site-translations.destroy'); + Route::post('/site-translations/batch-update', [SiteTranslationController::class, 'batchUpdate'])->name('api.site-translations.batch-update'); + Route::post('/site-translations/batch-destroy', [SiteTranslationController::class, 'batchDestroy'])->name('api.site-translations.batch-destroy'); +}); + // Products & Services Route::get('/urun-hizmet/{slug}', [\App\Http\Controllers\ProductController::class, 'show'])->name('products.show');