diff --git a/extensions/Servers/Proxmox/Livewire/Statistics.php b/extensions/Servers/Proxmox/Livewire/Statistics.php index ae26441c0..104cebe7b 100644 --- a/extensions/Servers/Proxmox/Livewire/Statistics.php +++ b/extensions/Servers/Proxmox/Livewire/Statistics.php @@ -48,6 +48,22 @@ class Statistics extends Component public int $networkAnalysisRetryCount = 0; public int $networkAnalysisMaxRetries = 3; + // Network Analysis Pagination + public int $connectionsPerPage = 25; + public int $connectionsCurrentPage = 1; + public int $topConnectionsPerPage = 25; + public int $topConnectionsCurrentPage = 1; + public int $topPortsPerPage = 25; + public int $topPortsCurrentPage = 1; + + // Statistics History Pagination + public int $statisticsPerPage = 25; + public int $statisticsCurrentPage = 1; + + // Task History Pagination + public int $taskHistoryPerPage = 25; + public int $taskHistoryCurrentPage = 1; + public array $networkAnalysis = [ 'connections' => [], 'topConnections' => [], @@ -377,16 +393,22 @@ class Statistics extends Component 'sample_connections' => array_slice($connections, 0, 3), ]); + // Store all connections without limit - pagination handles display $analysis = [ - 'connections' => array_slice($connections, 0, 100), - 'topConnections' => array_slice($topConnections, 0, 10), - 'topPorts' => array_slice($topPorts, 0, 10), + 'connections' => $connections, + 'topConnections' => $topConnections, + 'topPorts' => $topPorts, 'security' => $securityWarnings, 'lastUpdated' => now()->toDateTimeString(), 'error' => null, ]; $this->networkAnalysis = $analysis; + + // Reset pagination to page 1 when data is refreshed + $this->connectionsCurrentPage = 1; + $this->topConnectionsCurrentPage = 1; + $this->topPortsCurrentPage = 1; // Persist the computed analysis for a short period to speed up subsequent loads Cache::put($cacheKey, $analysis, now()->addSeconds(30)); @@ -446,6 +468,297 @@ class Statistics extends Component $this->networkAnalysisLoading = false; $this->loadNetworkAnalysis(); } + + // ========================================== + // Network Analysis Pagination Methods + // ========================================== + + /** + * Get paginated connections for display + */ + public function getPaginatedConnectionsProperty(): array + { + $connections = $this->networkAnalysis['connections'] ?? []; + $total = count($connections); + $offset = ($this->connectionsCurrentPage - 1) * $this->connectionsPerPage; + + return array_slice($connections, $offset, $this->connectionsPerPage); + } + + /** + * Get total pages for connections + */ + public function getConnectionsTotalPagesProperty(): int + { + $total = count($this->networkAnalysis['connections'] ?? []); + return max(1, (int) ceil($total / $this->connectionsPerPage)); + } + + /** + * Get paginated top connections for display + */ + public function getPaginatedTopConnectionsProperty(): array + { + $connections = $this->networkAnalysis['topConnections'] ?? []; + $offset = ($this->topConnectionsCurrentPage - 1) * $this->topConnectionsPerPage; + + return array_slice($connections, $offset, $this->topConnectionsPerPage); + } + + /** + * Get total pages for top connections + */ + public function getTopConnectionsTotalPagesProperty(): int + { + $total = count($this->networkAnalysis['topConnections'] ?? []); + return max(1, (int) ceil($total / $this->topConnectionsPerPage)); + } + + /** + * Get paginated top ports for display + */ + public function getPaginatedTopPortsProperty(): array + { + $ports = $this->networkAnalysis['topPorts'] ?? []; + $offset = ($this->topPortsCurrentPage - 1) * $this->topPortsPerPage; + + return array_slice($ports, $offset, $this->topPortsPerPage); + } + + /** + * Get total pages for top ports + */ + public function getTopPortsTotalPagesProperty(): int + { + $total = count($this->networkAnalysis['topPorts'] ?? []); + return max(1, (int) ceil($total / $this->topPortsPerPage)); + } + + /** + * Reset page to 1 when perPage changes for connections + */ + public function updatedConnectionsPerPage(): void + { + $this->connectionsCurrentPage = 1; + } + + /** + * Reset page to 1 when perPage changes for top connections + */ + public function updatedTopConnectionsPerPage(): void + { + $this->topConnectionsCurrentPage = 1; + } + + /** + * Reset page to 1 when perPage changes for top ports + */ + public function updatedTopPortsPerPage(): void + { + $this->topPortsCurrentPage = 1; + } + + /** + * Navigate to a specific page for connections + */ + public function goToConnectionsPage(int $page): void + { + $this->connectionsCurrentPage = max(1, min($page, $this->connectionsTotalPages)); + } + + /** + * Navigate to previous page for connections + */ + public function previousConnectionsPage(): void + { + $this->goToConnectionsPage($this->connectionsCurrentPage - 1); + } + + /** + * Navigate to next page for connections + */ + public function nextConnectionsPage(): void + { + $this->goToConnectionsPage($this->connectionsCurrentPage + 1); + } + + /** + * Navigate to a specific page for top connections + */ + public function goToTopConnectionsPage(int $page): void + { + $this->topConnectionsCurrentPage = max(1, min($page, $this->topConnectionsTotalPages)); + } + + /** + * Navigate to previous page for top connections + */ + public function previousTopConnectionsPage(): void + { + $this->goToTopConnectionsPage($this->topConnectionsCurrentPage - 1); + } + + /** + * Navigate to next page for top connections + */ + public function nextTopConnectionsPage(): void + { + $this->goToTopConnectionsPage($this->topConnectionsCurrentPage + 1); + } + + /** + * Navigate to a specific page for top ports + */ + public function goToTopPortsPage(int $page): void + { + $this->topPortsCurrentPage = max(1, min($page, $this->topPortsTotalPages)); + } + + /** + * Navigate to previous page for top ports + */ + public function previousTopPortsPage(): void + { + $this->goToTopPortsPage($this->topPortsCurrentPage - 1); + } + + /** + * Navigate to next page for top ports + */ + public function nextTopPortsPage(): void + { + $this->goToTopPortsPage($this->topPortsCurrentPage + 1); + } + + // ========================================== + // Statistics History Pagination Methods + // ========================================== + + /** + * Get all statistics for pagination (raw data) + */ + public function getAllStatisticsProperty(): \Illuminate\Database\Eloquent\Collection + { + return ServerStatistics::where('server_id', $this->server->id) + ->orderBy('DateTime', 'desc') + ->get(); + } + + /** + * Get paginated statistics for display + */ + public function getPaginatedStatisticsProperty(): array + { + $statistics = $this->allStatistics; + $offset = ($this->statisticsCurrentPage - 1) * $this->statisticsPerPage; + + return $statistics->slice($offset, $this->statisticsPerPage)->values()->all(); + } + + /** + * Get total pages for statistics + */ + public function getStatisticsTotalPagesProperty(): int + { + $total = $this->allStatistics->count(); + return max(1, (int) ceil($total / $this->statisticsPerPage)); + } + + /** + * Reset page to 1 when perPage changes for statistics + */ + public function updatedStatisticsPerPage(): void + { + $this->statisticsCurrentPage = 1; + } + + /** + * Navigate to a specific page for statistics + */ + public function goToStatisticsPage(int $page): void + { + $this->statisticsCurrentPage = max(1, min($page, $this->statisticsTotalPages)); + } + + /** + * Navigate to previous page for statistics + */ + public function previousStatisticsPage(): void + { + $this->goToStatisticsPage($this->statisticsCurrentPage - 1); + } + + /** + * Navigate to next page for statistics + */ + public function nextStatisticsPage(): void + { + $this->goToStatisticsPage($this->statisticsCurrentPage + 1); + } + + // ========================================== + // Task History Pagination Methods + // ========================================== + + /** + * Get all task history for pagination (raw data) + */ + public function getAllTaskHistoryProperty(): array + { + return $this->taskHistory; + } + + /** + * Get paginated task history for display + */ + public function getPaginatedTaskHistoryProperty(): array + { + $tasks = $this->allTaskHistory; + $offset = ($this->taskHistoryCurrentPage - 1) * $this->taskHistoryPerPage; + + return array_slice($tasks, $offset, $this->taskHistoryPerPage); + } + + /** + * Get total pages for task history + */ + public function getTaskHistoryTotalPagesProperty(): int + { + $total = count($this->allTaskHistory); + return max(1, (int) ceil($total / $this->taskHistoryPerPage)); + } + + /** + * Reset page to 1 when perPage changes for task history + */ + public function updatedTaskHistoryPerPage(): void + { + $this->taskHistoryCurrentPage = 1; + } + + /** + * Navigate to a specific page for task history + */ + public function goToTaskHistoryPage(int $page): void + { + $this->taskHistoryCurrentPage = max(1, min($page, $this->taskHistoryTotalPages)); + } + + /** + * Navigate to previous page for task history + */ + public function previousTaskHistoryPage(): void + { + $this->goToTaskHistoryPage($this->taskHistoryCurrentPage - 1); + } + + /** + * Navigate to next page for task history + */ + public function nextTaskHistoryPage(): void + { + $this->goToTaskHistoryPage($this->taskHistoryCurrentPage + 1); + } /** * Extract IP address from field (handles "IP[port]" and "IP:port" formats) @@ -797,7 +1110,7 @@ class Statistics extends Component { return ServerStatistics::where('server_id', $this->server->id) ->orderBy('DateTime', 'desc') - ->paginate(50); + ->paginate($this->statisticsPerPage); } public function deleteStatistic($statisticId) diff --git a/extensions/Servers/Proxmox/views/statistics.blade.php b/extensions/Servers/Proxmox/views/statistics.blade.php index 1b1ec56c6..7cd07ccdc 100644 --- a/extensions/Servers/Proxmox/views/statistics.blade.php +++ b/extensions/Servers/Proxmox/views/statistics.blade.php @@ -897,11 +897,31 @@ - @if($this->statistics->hasPages()) -
- {{ $this->statistics->links() }} + +
+
+ +
+ Show + + entries + ({{ $this->statistics->total() }} total) +
+ + + @if($this->statistics->hasPages()) +
+ {{ $this->statistics->links() }} +
+ @endif
- @endif +
@@ -2160,12 +2180,12 @@ - @foreach($networkAnalysis['connections'] as $index => $connection) + @foreach($this->paginatedConnections as $index => $connection) @php // Use raw bytes value from backend for reliable numeric sorting $bytesForSort = (int)($connection['bytes'] ?? 0); @endphp - + + {{-- Connections Pagination Controls --}} + @if(count($networkAnalysis['connections']) > 0) +
+ {{-- Records per page selector --}} +
+ + + per page +
+ + {{-- Page info and navigation --}} +
+ + Showing {{ (($connectionsCurrentPage - 1) * $connectionsPerPage) + 1 }} - {{ min($connectionsCurrentPage * $connectionsPerPage, count($networkAnalysis['connections'])) }} of {{ count($networkAnalysis['connections']) }} connections + + +
+ {{-- First page --}} + + + {{-- Previous page --}} + + + {{-- Page numbers --}} + @php + $connectionsTotalPages = $this->connectionsTotalPages; + $startPage = max(1, $connectionsCurrentPage - 2); + $endPage = min($connectionsTotalPages, $connectionsCurrentPage + 2); + @endphp + + @if($startPage > 1) + + @if($startPage > 2) + ... + @endif + @endif + + @for($i = $startPage; $i <= $endPage; $i++) + + @endfor + + @if($endPage < $connectionsTotalPages) + @if($endPage < $connectionsTotalPages - 1) + ... + @endif + + @endif + + {{-- Next page --}} + + + {{-- Last page --}} + +
+
+
+ @endif @endif @@ -2617,7 +2729,7 @@ - @foreach($networkAnalysis['topConnections'] as $index => $row) + @foreach($this->paginatedTopConnections as $index => $row) @php $endpointIP = $row['endpoint'] ?? '—'; $port = $row['port'] ?? 0; @@ -2625,7 +2737,7 @@ $bytes = $row['bytes'] ?? 0; $bytesForSort = $bytes; @endphp - + + {{-- Top Connections Pagination Controls --}} + @if(count($networkAnalysis['topConnections']) > 0) +
+ {{-- Records per page selector --}} +
+ + + per page +
+ + {{-- Page info and navigation --}} +
+ + Showing {{ (($topConnectionsCurrentPage - 1) * $topConnectionsPerPage) + 1 }} - {{ min($topConnectionsCurrentPage * $topConnectionsPerPage, count($networkAnalysis['topConnections'])) }} of {{ count($networkAnalysis['topConnections']) }} peers + + +
+ {{-- First page --}} + + + {{-- Previous page --}} + + + {{-- Page numbers --}} + @php + $topConnectionsTotalPages = $this->topConnectionsTotalPages; + $startPage = max(1, $topConnectionsCurrentPage - 2); + $endPage = min($topConnectionsTotalPages, $topConnectionsCurrentPage + 2); + @endphp + + @if($startPage > 1) + + @if($startPage > 2) + ... + @endif + @endif + + @for($i = $startPage; $i <= $endPage; $i++) + + @endfor + + @if($endPage < $topConnectionsTotalPages) + @if($endPage < $topConnectionsTotalPages - 1) + ... + @endif + + @endif + + {{-- Next page --}} + + + {{-- Last page --}} + +
+
+
+ @endif @endif @@ -2842,14 +3046,14 @@ - @foreach($networkAnalysis['topPorts'] as $index => $row) + @foreach($this->paginatedTopPorts as $index => $row) @php $port = $row['port'] ?? 0; $connections = $row['connections'] ?? 0; $bytes = $row['bytes'] ?? 0; $bytesForSort = $bytes; @endphp - @@ -2913,6 +3117,98 @@ + + {{-- Top Ports Pagination Controls --}} + @if(count($networkAnalysis['topPorts']) > 0) +
+ {{-- Records per page selector --}} +
+ + + per page +
+ + {{-- Page info and navigation --}} +
+ + Showing {{ (($topPortsCurrentPage - 1) * $topPortsPerPage) + 1 }} - {{ min($topPortsCurrentPage * $topPortsPerPage, count($networkAnalysis['topPorts'])) }} of {{ count($networkAnalysis['topPorts']) }} ports + + +
+ {{-- First page --}} + + + {{-- Previous page --}} + + + {{-- Page numbers --}} + @php + $topPortsTotalPages = $this->topPortsTotalPages; + $startPage = max(1, $topPortsCurrentPage - 2); + $endPage = min($topPortsTotalPages, $topPortsCurrentPage + 2); + @endphp + + @if($startPage > 1) + + @if($startPage > 2) + ... + @endif + @endif + + @for($i = $startPage; $i <= $endPage; $i++) + + @endfor + + @if($endPage < $topPortsTotalPages) + @if($endPage < $topPortsTotalPages - 1) + ... + @endif + + @endif + + {{-- Next page --}} + + + {{-- Last page --}} + +
+
+
+ @endif @endif