Implement Site Translations API and DataGrid View: Introduced a new API controller for managing site translations, including methods for listing, storing, updating, and deleting translations. Added a DataGrid view for the site translations page, allowing for enhanced user interaction and management of translations. Implemented session-based view toggling between traditional table and DataGrid formats, improving usability. Localization support has been integrated for all text elements, ensuring a seamless experience for users across different languages.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\SiteTranslation;
|
||||
use App\Models\Language;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class SiteTranslationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$query = SiteTranslation::query();
|
||||
|
||||
// Search
|
||||
if ($request->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.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
<x-filament-panels::page>
|
||||
@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
|
||||
|
||||
<div id="site-translations-datagrid" style="margin-top: 1rem;">
|
||||
<div style="padding: 20px; text-align: center; color: #666;">
|
||||
<p>DataGrid yükleniyor...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#site-translations-datagrid {
|
||||
width: 100%;
|
||||
height: calc(100vh - 250px);
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.dx-datagrid-headers {
|
||||
background-color: var(--fi-primary-50, #f0f9ff);
|
||||
}
|
||||
|
||||
.dx-state-focused {
|
||||
border-color: var(--fi-primary-600, #0284c7);
|
||||
}
|
||||
|
||||
.dx-button.dx-button-success {
|
||||
background-color: var(--fi-success-600, #16a34a);
|
||||
border-color: var(--fi-success-600, #16a34a);
|
||||
}
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/23.1.5/css/dx.light.css" />
|
||||
<script src="https://cdn3.devexpress.com/jslib/23.1.5/js/dx.all.js"></script>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
function initializeDataGrid() {
|
||||
// DOM element'inin hazır olduğunu kontrol et
|
||||
const gridElement = document.getElementById('site-translations-datagrid');
|
||||
if (!gridElement) {
|
||||
console.error('DataGrid container bulunamadı!');
|
||||
setTimeout(initializeDataGrid, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// DevExtreme'in yüklendiğini kontrol et
|
||||
if (typeof DevExpress === 'undefined') {
|
||||
console.error('DevExtreme yüklenemedi!');
|
||||
gridElement.innerHTML =
|
||||
'<div style="padding: 20px; color: red;">DevExtreme kütüphanesi yüklenemedi. Lütfen sayfayı yenileyin.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('DevExtreme yüklendi, DataGrid başlatılıyor...');
|
||||
|
||||
const languages = @json($languages->map(fn($lang) => ['code' => $lang->code, 'name' => $lang->name]));
|
||||
const apiUrl = @json($apiUrl);
|
||||
const apiStoreUrl = @json($apiStoreUrl);
|
||||
const apiUpdateUrl = @json($apiUpdateUrl);
|
||||
const apiDeleteUrl = @json($apiDeleteUrl);
|
||||
const apiBatchUpdateUrl = @json($apiBatchUpdateUrl);
|
||||
const apiBatchDeleteUrl = @json($apiBatchDeleteUrl);
|
||||
const csrfToken = @json($csrfToken);
|
||||
|
||||
// Column definitions
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'key',
|
||||
caption: 'Key / Orijinal Metin',
|
||||
width: 300,
|
||||
allowEditing: true,
|
||||
editorType: 'dxTextArea',
|
||||
editorOptions: {
|
||||
height: 60
|
||||
},
|
||||
validationRules: [{ type: 'required', message: 'Key gereklidir' }]
|
||||
}
|
||||
];
|
||||
|
||||
// Add language columns
|
||||
languages.forEach(lang => {
|
||||
columns.push({
|
||||
dataField: lang.code,
|
||||
caption: `${lang.name} (${lang.code})`,
|
||||
allowEditing: true,
|
||||
width: 250,
|
||||
editorType: 'dxTextArea',
|
||||
editorOptions: {
|
||||
height: 80,
|
||||
maxHeight: 200
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
columns.push({
|
||||
dataField: 'created_at',
|
||||
caption: 'Oluşturulma',
|
||||
dataType: 'datetime',
|
||||
allowEditing: false,
|
||||
width: 150,
|
||||
visible: false
|
||||
});
|
||||
|
||||
columns.push({
|
||||
dataField: 'updated_at',
|
||||
caption: 'Güncellenme',
|
||||
dataType: 'datetime',
|
||||
allowEditing: false,
|
||||
width: 150,
|
||||
visible: false
|
||||
});
|
||||
|
||||
// Helper function for API calls
|
||||
function apiCall(url, method, data) {
|
||||
const options = {
|
||||
method: method,
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': csrfToken,
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
if (data) {
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
return fetch(url, options)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('API Error:', error);
|
||||
return { success: false, message: error.message };
|
||||
});
|
||||
}
|
||||
|
||||
// DataGrid configuration
|
||||
const dataGrid = new DevExpress.data.DataSource({
|
||||
load: function(loadOptions) {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Pagination
|
||||
if (loadOptions.skip !== undefined && loadOptions.take) {
|
||||
params.append('page', Math.floor(loadOptions.skip / loadOptions.take) + 1);
|
||||
params.append('pageSize', loadOptions.take);
|
||||
} else {
|
||||
params.append('page', '1');
|
||||
params.append('pageSize', '20');
|
||||
}
|
||||
|
||||
// Sorting
|
||||
if (loadOptions.sort) {
|
||||
loadOptions.sort.forEach(sort => {
|
||||
params.append('sort', sort.selector || sort);
|
||||
params.append('order', sort.desc ? 'desc' : 'asc');
|
||||
});
|
||||
}
|
||||
|
||||
// Search
|
||||
if (loadOptions.searchValue) {
|
||||
params.append('search', loadOptions.searchValue);
|
||||
}
|
||||
|
||||
const requestUrl = apiUrl + '?' + params.toString();
|
||||
console.log('DataGrid loading data from:', requestUrl);
|
||||
|
||||
return apiCall(requestUrl, 'GET')
|
||||
.then(function(response) {
|
||||
console.log('DataGrid API response:', response);
|
||||
if (!response || !response.data) {
|
||||
console.error('Invalid API response:', response);
|
||||
return {
|
||||
data: [],
|
||||
totalCount: 0
|
||||
};
|
||||
}
|
||||
return {
|
||||
data: response.data || [],
|
||||
totalCount: response.totalCount || 0
|
||||
};
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('DataGrid load error:', error);
|
||||
DevExpress.ui.notify('Veri yüklenirken hata oluştu: ' + (error.message || 'Bilinmeyen hata'), 'error', 5000);
|
||||
return {
|
||||
data: [],
|
||||
totalCount: 0
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const dataGridInstance = new DevExpress.ui.dxDataGrid(gridElement, {
|
||||
dataSource: dataGrid,
|
||||
columns: columns,
|
||||
editing: {
|
||||
mode: 'batch',
|
||||
allowAdding: true,
|
||||
allowUpdating: true,
|
||||
allowDeleting: true,
|
||||
useIcons: true,
|
||||
texts: {
|
||||
addRow: 'Yeni Ekle',
|
||||
saveAllChanges: 'Tüm Değişiklikleri Kaydet',
|
||||
cancelAllChanges: 'İptal',
|
||||
confirmDeleteMessage: 'Bu kaydı silmek istediğinizden emin misiniz?'
|
||||
}
|
||||
},
|
||||
searchPanel: {
|
||||
visible: true,
|
||||
width: 300,
|
||||
placeholder: 'Ara...'
|
||||
},
|
||||
headerFilter: {
|
||||
visible: true
|
||||
},
|
||||
filterRow: {
|
||||
visible: true
|
||||
},
|
||||
paging: {
|
||||
pageSize: 20,
|
||||
pageIndex: 0
|
||||
},
|
||||
pager: {
|
||||
showPageSizeSelector: true,
|
||||
allowedPageSizes: [10, 20, 50, 100],
|
||||
showInfo: true,
|
||||
showNavigationButtons: true
|
||||
},
|
||||
sorting: {
|
||||
mode: 'multiple'
|
||||
},
|
||||
showBorders: true,
|
||||
rowAlternationEnabled: true,
|
||||
hoverStateEnabled: true,
|
||||
columnAutoWidth: true,
|
||||
allowColumnResizing: true,
|
||||
columnResizingMode: 'widget',
|
||||
wordWrapEnabled: true,
|
||||
onSaving: function(e) {
|
||||
e.cancel = true;
|
||||
|
||||
const changes = e.changes || [];
|
||||
const insertPromises = [];
|
||||
const updateChanges = [];
|
||||
const deletePromises = [];
|
||||
|
||||
// Separate changes by type
|
||||
changes.forEach(function(change) {
|
||||
if (change.type === 'insert') {
|
||||
const requestData = {
|
||||
key: change.data.key || ''
|
||||
};
|
||||
|
||||
languages.forEach(lang => {
|
||||
if (change.data[lang.code] !== undefined) {
|
||||
requestData[lang.code] = change.data[lang.code] || '';
|
||||
}
|
||||
});
|
||||
|
||||
insertPromises.push(apiCall(apiStoreUrl, 'POST', requestData));
|
||||
} else if (change.type === 'update') {
|
||||
const oldData = change.key;
|
||||
const newData = change.data;
|
||||
const requestData = {
|
||||
key: newData.key !== undefined ? newData.key : oldData.key
|
||||
};
|
||||
|
||||
languages.forEach(lang => {
|
||||
if (newData[lang.code] !== undefined) {
|
||||
requestData[lang.code] = newData[lang.code] || '';
|
||||
} else if (oldData[lang.code] !== undefined) {
|
||||
requestData[lang.code] = oldData[lang.code] || '';
|
||||
}
|
||||
});
|
||||
|
||||
updateChanges.push({
|
||||
key: oldData.id,
|
||||
data: requestData
|
||||
});
|
||||
} else if (change.type === 'remove') {
|
||||
deletePromises.push(
|
||||
apiCall(apiDeleteUrl.replace('__ID__', change.key.id), 'DELETE')
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle batch updates
|
||||
let updatePromise = Promise.resolve({ success: true, updated: [] });
|
||||
if (updateChanges.length > 0) {
|
||||
updatePromise = apiCall(apiBatchUpdateUrl, 'POST', {
|
||||
changes: updateChanges
|
||||
});
|
||||
}
|
||||
|
||||
// Execute all promises
|
||||
Promise.all([
|
||||
Promise.all(insertPromises),
|
||||
updatePromise,
|
||||
Promise.all(deletePromises)
|
||||
]).then(function(results) {
|
||||
const [insertResults, updateResult, deleteResults] = results;
|
||||
let successCount = 0;
|
||||
let errorCount = 0;
|
||||
let errorMessages = [];
|
||||
|
||||
insertResults.forEach(function(result) {
|
||||
if (result.success) {
|
||||
successCount++;
|
||||
} else {
|
||||
errorCount++;
|
||||
if (result.message) errorMessages.push(result.message);
|
||||
}
|
||||
});
|
||||
|
||||
if (updateResult.success) {
|
||||
successCount += updateResult.updated ? updateResult.updated.length : 0;
|
||||
if (updateResult.errors && updateResult.errors.length > 0) {
|
||||
errorCount += updateResult.errors.length;
|
||||
errorMessages = errorMessages.concat(updateResult.errors);
|
||||
}
|
||||
} else {
|
||||
errorCount++;
|
||||
if (updateResult.message) errorMessages.push(updateResult.message);
|
||||
}
|
||||
|
||||
deleteResults.forEach(function(result) {
|
||||
if (result.success) {
|
||||
successCount++;
|
||||
} else {
|
||||
errorCount++;
|
||||
if (result.message) errorMessages.push(result.message);
|
||||
}
|
||||
});
|
||||
|
||||
if (errorCount === 0) {
|
||||
DevExpress.ui.notify(
|
||||
`${successCount} işlem başarıyla tamamlandı`,
|
||||
'success',
|
||||
3000
|
||||
);
|
||||
e.component.refresh();
|
||||
} else {
|
||||
const message = errorMessages.length > 0
|
||||
? errorMessages.join('; ')
|
||||
: `${errorCount} işlem başarısız oldu`;
|
||||
DevExpress.ui.notify(message, 'error', 5000);
|
||||
e.component.refresh();
|
||||
}
|
||||
}).catch(function(error) {
|
||||
DevExpress.ui.notify(
|
||||
'İşlem sırasında hata oluştu: ' + (error.message || 'Bilinmeyen hata'),
|
||||
'error',
|
||||
5000
|
||||
);
|
||||
e.component.refresh();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log('DataGrid başlatıldı:', dataGridInstance);
|
||||
}
|
||||
|
||||
// Sayfa yüklendiğinde başlat
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setTimeout(initializeDataGrid, 500);
|
||||
});
|
||||
} else {
|
||||
// DOM zaten hazır, DevExtreme yüklenene kadar bekle
|
||||
setTimeout(initializeDataGrid, 500);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</x-filament-panels::page>
|
||||
@@ -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');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user