dataTable($request); } return view('pages.access_control.action-logs'); } protected function dataTable(Request $request) { try { $query = Activity::query()->with('causer'); // Fast count without eager loading or ordering $recordsTotal = Activity::count(); $globalSearch = DataTable::globalSearch($request); if ($event = $request->input('event')) { if ($event === 'auth') { $query->whereIn('description', ['login', 'logout', 'login_attempt', 'password_changed', 'failed login', 'password reset']); } elseif ($event === 'data') { $query->whereIn('description', ['created', 'updated', 'deleted', 'restored', 'force deleted', 'permanent_deleted']); } elseif ($event === 'system') { $query->whereIn('log_name', ['system', 'maintenance', 'backup']); } } if ($user = DataTable::columnSearch($request, 0)) { $query->whereHas('causer', function ($causerQuery) use ($user) { $causerQuery->where(function ($q) use ($user) { $q->where('name', 'like', "%{$user}%") ->orWhere('email', 'like', "%{$user}%"); }); }); } if ($action = DataTable::columnSearch($request, 1)) { $query->where('description', 'like', "%{$action}%"); } if ($details = DataTable::columnSearch($request, 2)) { $query->where('properties', 'like', "%{$details}%"); } if ($module = DataTable::columnSearch($request, 3)) { $query->where('log_name', 'like', "%{$module}%"); } if ($executedAt = DataTable::columnSearch($request, 4)) { $query->whereDate('created_at', $executedAt); } if ($ip = DataTable::columnSearch($request, 5)) { $query->where('properties->ip', 'like', "%{$ip}%"); } if ($agent = DataTable::columnSearch($request, 6)) { $query->where('properties->agent', 'like', "%{$agent}%"); } if ($properties = DataTable::columnSearch($request, 7)) { $query->where('properties', 'like', "%{$properties}%"); } if ($globalSearch) { $query->where(function ($searchQuery) use ($globalSearch) { $searchQuery ->where('description', 'like', "%{$globalSearch}%") ->orWhere('log_name', 'like', "%{$globalSearch}%") ->orWhere('properties', 'like', "%{$globalSearch}%") ->orWhereHas('causer', function ($causerQuery) use ($globalSearch) { $causerQuery->where('email', 'like', "%{$globalSearch}%"); }); }); } [$orderIndex, $orderDirection] = DataTable::order($request, 4, 'desc'); $sortColumn = match ($orderIndex) { 0 => 'causer_type', 1 => 'description', 3 => 'log_name', 4 => 'created_at', default => 'created_at', }; // Remove old global ordering and apply datatable specific ordering $query->orderBy($sortColumn, $orderDirection); // Perform filtered count WITHOUT eager loading or ordering $countQuery = clone $query; $countQuery->setEagerLoads([]); $countQuery->orders = null; $recordsFiltered = $countQuery->count(); $logs = $query ->skip(DataTable::start($request)) ->take(DataTable::length($request)) ->get(); $rows = $logs->map(function (Activity $log) { $properties = is_array($log->properties) ? $log->properties : $log->properties?->toArray(); $eventLabel = ucfirst($log->description); $eventBadge = ActivityFormatter::getEventBadgeClass($log->description); $eventIcon = ActivityFormatter::getEventIcon($log->description); $modelName = ActivityFormatter::getFriendlyModelName($log->subject_type); $changes = ActivityFormatter::formatChanges($properties ?? []); // User Column (Removed icon) $userHtml = '
'.e($log->causer?->name ?? 'System').'
'.e($log->causer?->email ?? 'no-email').'
'; // Event Column $eventHtml = ' '.$eventLabel.' '; // Information Column (Preview of changes) $infoHtml = '
'; if (! empty($changes)) { $first = $changes[0]; $infoHtml .= ''.e($first['field']).': '.e($first['new']); if (count($changes) > 1) { $infoHtml .= ' +'.(count($changes) - 1).''; } } else { $infoHtml .= e(data_get($properties, 'details', '-')); } $infoHtml .= '
'; // Logistics Column $ip = data_get($properties, 'ip', '-'); $agent = data_get($properties, 'agent', '-'); // Prepare JSON for modal $modalData = [ 'causer' => [ 'name' => $log->causer?->name ?? 'System', 'email' => $log->causer?->email ?? '-', ], 'event' => [ 'label' => $eventLabel, 'badge' => $eventBadge, 'icon' => $eventIcon, 'description' => $log->description, ], 'subject' => [ 'type' => $modelName, 'id' => $log->subject_id, 'module' => $log->log_name, ], 'changes' => $changes, 'meta' => [ 'ip' => $ip, 'agent' => $agent, 'time' => format_datetime($log->created_at), ], 'raw' => $log->toArray(), ]; return [ $userHtml, $eventHtml, $infoHtml, ''.e($modelName).'', e(format_datetime($log->created_at)), ''.e($ip).'', ''.e($agent).'', '
'.e(json_encode($properties)).'
', '
', ]; })->all(); return DataTable::response($request, $recordsTotal, $recordsFiltered, $rows); } catch (\Exception $e) { Log::error('DataTable Error [ActionLog]: '.$e->getMessage()); return DataTable::response($request, 0, 0, []); } } public function clear() { try { DB::table('activity_log')->truncate(); return response()->json(['success' => true, 'message' => __('Action logs cleared successfully.')]); } catch (\Exception $e) { return response()->json(['success' => false, 'message' => __('Failed to clear logs.')], 500); } } public function export(Request $request) { $query = Activity::query()->with('causer')->latest(); // Apply same filters as dataTable if ($event = $request->input('event')) { if ($event === 'auth') { $query->whereIn('description', ['login', 'logout', 'login_attempt', 'password_changed', 'failed login', 'password reset']); } elseif ($event === 'data') { $query->whereIn('description', ['created', 'updated', 'deleted', 'restored', 'force deleted', 'permanent_deleted']); } elseif ($event === 'system') { $query->whereIn('log_name', ['system', 'maintenance', 'backup']); } } if ($search = $request->input('search')) { $query->where(function ($q) use ($search) { $q->where('description', 'like', "%{$search}%") ->orWhere('log_name', 'like', "%{$search}%") ->orWhere('properties', 'like', "%{$search}%"); }); } $filename = 'action-logs-'.now()->format('Y-m-d-His').'.csv'; return response()->streamDownload(function () use ($query) { $file = fopen('php://output', 'w'); fputcsv($file, ['User', 'Action', 'Module', 'Executed At', 'IP Address', 'User Agent', 'Properties']); $query->chunk(200, function ($logs) use ($file) { foreach ($logs as $log) { fputcsv($file, [ $log->causer?->name ?? 'System', ucfirst($log->description), $log->log_name, $log->created_at->toDateTimeString(), data_get($log->properties, 'ip', '-'), data_get($log->properties, 'agent', '-'), json_encode($log->properties), ]); } }); fclose($file); }, $filename); } }