mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-29 16:01:29 +00:00
219 lines
8.3 KiB
PHP
219 lines
8.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\BasePageController;
|
|
use App\Services\AdminDashboardSnapshotService;
|
|
use App\Services\RegistrationStatusService;
|
|
use App\Services\SiteStatusService;
|
|
use App\Services\SystemMetricsService;
|
|
use App\Services\UserStatsService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Support\Carbon;
|
|
|
|
class AdminPageController extends BasePageController
|
|
{
|
|
protected UserStatsService $userStatsService;
|
|
|
|
protected SystemMetricsService $systemMetricsService;
|
|
|
|
protected RegistrationStatusService $registrationStatusService;
|
|
|
|
protected SiteStatusService $siteStatusService;
|
|
|
|
protected AdminDashboardSnapshotService $snapshot;
|
|
|
|
public function __construct(
|
|
UserStatsService $userStatsService,
|
|
SystemMetricsService $systemMetricsService,
|
|
RegistrationStatusService $registrationStatusService,
|
|
SiteStatusService $siteStatusService,
|
|
AdminDashboardSnapshotService $snapshot,
|
|
) {
|
|
parent::__construct();
|
|
$this->userStatsService = $userStatsService;
|
|
$this->systemMetricsService = $systemMetricsService;
|
|
$this->registrationStatusService = $registrationStatusService;
|
|
$this->siteStatusService = $siteStatusService;
|
|
$this->snapshot = $snapshot;
|
|
}
|
|
|
|
/**
|
|
* @throws \Exception
|
|
*/
|
|
public function index(): mixed
|
|
{
|
|
$this->setAdminPrefs();
|
|
|
|
$payload = $this->snapshot->get();
|
|
|
|
return view('admin.dashboard', array_merge($this->viewData, [
|
|
'meta_title' => 'Admin Home',
|
|
'meta_description' => 'Admin home page',
|
|
// Lightweight data is rendered server-side; heavy widgets fetch on mount.
|
|
'stats' => $payload['stats'],
|
|
'registrationStatus' => $payload['registrationStatus'],
|
|
'nextRegistrationPeriod' => $payload['nextRegistrationPeriod'],
|
|
'hasRecentPayments' => ! empty($payload['recent_payments']),
|
|
]));
|
|
}
|
|
|
|
/**
|
|
* JSON payload consumed by the dashboard's deferred widgets (User Statistics,
|
|
* System Resources history, Recent Activity, Site Status) and by the
|
|
* client-side auto-refresh which also re-renders the headline stat tiles
|
|
* and the registration status panel from this payload. Reads from the
|
|
* same snapshot cache the index uses, so the warmer keeps it hot.
|
|
*/
|
|
public function getDashboardData(): JsonResponse
|
|
{
|
|
$payload = $this->snapshot->get();
|
|
|
|
$serviceStatuses = collect($payload['serviceStatuses'])->map(static fn ($svc) => [
|
|
'name' => $svc->name,
|
|
'slug' => $svc->slug,
|
|
'check_type' => $svc->check_type,
|
|
'status' => $svc->status->value,
|
|
'status_label' => $svc->status->label(),
|
|
'uptime_percentage' => (float) $svc->uptime_percentage,
|
|
])->values();
|
|
|
|
$activeIncidents = collect($payload['activeIncidents'])->map(static fn ($incident) => [
|
|
'id' => $incident->id,
|
|
'title' => $incident->title,
|
|
'impact' => $incident->impact->value,
|
|
'impact_label' => $incident->impact->label(),
|
|
'started_at' => $incident->started_at?->toIso8601String(),
|
|
'started_at_human' => $incident->started_at?->diffForHumans(),
|
|
'is_auto' => (bool) $incident->is_auto,
|
|
'services' => $incident->services->pluck('name')->all(),
|
|
])->values();
|
|
|
|
$recentActivity = array_map(static fn ($activity): array => [
|
|
'type' => $activity->type,
|
|
'message' => $activity->message,
|
|
'icon' => $activity->icon,
|
|
'icon_bg' => $activity->icon_bg,
|
|
'icon_color' => $activity->icon_color,
|
|
'created_at' => $activity->created_at?->toIso8601String(),
|
|
'created_at_human' => $activity->created_at?->diffForHumans(),
|
|
'username' => $activity->username,
|
|
'metadata' => $activity->metadata,
|
|
], $payload['recent_activity']);
|
|
|
|
$registrationStatus = $payload['registrationStatus'];
|
|
$serializePeriod = static fn ($period): ?array => $period === null ? null : [
|
|
'id' => $period->id,
|
|
'name' => $period->name,
|
|
'starts_at' => $period->starts_at?->format('Y-m-d H:i'),
|
|
'ends_at' => $period->ends_at?->format('Y-m-d H:i'),
|
|
];
|
|
|
|
$registrationPayload = [
|
|
'manual_status' => $registrationStatus['manual_status'],
|
|
'manual_status_label' => $registrationStatus['manual_status_label'],
|
|
'effective_status' => $registrationStatus['effective_status'],
|
|
'effective_status_label' => $registrationStatus['effective_status_label'],
|
|
'scheduled_override_active' => (bool) $registrationStatus['scheduled_override_active'],
|
|
'message' => $registrationStatus['message'],
|
|
'active_period' => $serializePeriod($registrationStatus['active_period']),
|
|
];
|
|
|
|
$generatedAt = $payload['generated_at'] ?? now()->toIso8601String();
|
|
$generatedAtCarbon = Carbon::parse($generatedAt);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'generated_at' => $generatedAt,
|
|
'generated_at_time' => $generatedAtCarbon->format('H:i:s'),
|
|
'stats' => $payload['stats'],
|
|
'registrationStatus' => $registrationPayload,
|
|
'nextRegistrationPeriod' => $serializePeriod($payload['nextRegistrationPeriod']),
|
|
'userStats' => $payload['userStats'],
|
|
'systemMetrics' => $payload['systemMetrics'],
|
|
'recent_activity' => $recentActivity,
|
|
'recent_payments' => $payload['recent_payments'] ?? [],
|
|
'serviceStatuses' => $serviceStatuses,
|
|
'activeIncidents' => $activeIncidents,
|
|
]);
|
|
}
|
|
|
|
public function getRecentActivity(): JsonResponse
|
|
{
|
|
$payload = $this->snapshot->get();
|
|
|
|
$activities = array_map(static fn ($activity): array => [
|
|
'type' => $activity->type,
|
|
'message' => $activity->message,
|
|
'icon' => $activity->icon,
|
|
'icon_bg' => $activity->icon_bg,
|
|
'icon_color' => $activity->icon_color,
|
|
'created_at' => $activity->created_at?->diffForHumans(),
|
|
'username' => $activity->username,
|
|
'metadata' => $activity->metadata,
|
|
], $payload['recent_activity']);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'activities' => $activities,
|
|
]);
|
|
}
|
|
|
|
public function getUserActivityMinutes(): JsonResponse
|
|
{
|
|
$downloadsPerMinute = $this->userStatsService->getDownloadsPerMinute(60);
|
|
$apiHitsPerMinute = $this->userStatsService->getApiHitsPerMinute(60);
|
|
|
|
return response()->json([
|
|
'downloads' => $downloadsPerMinute,
|
|
'api_hits' => $apiHitsPerMinute,
|
|
]);
|
|
}
|
|
|
|
public function getCurrentMetrics(): JsonResponse
|
|
{
|
|
$cpuUsage = $this->systemMetricsService->getCpuUsage();
|
|
$ramUsage = $this->systemMetricsService->getRamUsage();
|
|
$cpuInfo = $this->systemMetricsService->getCpuInfo();
|
|
$loadAverage = $this->systemMetricsService->getLoadAverage();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'cpu' => [
|
|
'current' => $cpuUsage,
|
|
'cores' => $cpuInfo['cores'],
|
|
'threads' => $cpuInfo['threads'],
|
|
'model' => $cpuInfo['model'],
|
|
'load_average' => $loadAverage,
|
|
],
|
|
'ram' => [
|
|
'used' => $ramUsage['used'],
|
|
'total' => $ramUsage['total'],
|
|
'percentage' => $ramUsage['percentage'],
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function getHistoricalMetrics(): JsonResponse
|
|
{
|
|
$timeRange = request('range', '24h');
|
|
|
|
if ($timeRange === '30d') {
|
|
$cpuHistory = $this->systemMetricsService->getDailyMetrics('cpu', 30);
|
|
$ramHistory = $this->systemMetricsService->getDailyMetrics('ram', 30);
|
|
} else {
|
|
$cpuHistory = $this->systemMetricsService->getHourlyMetrics('cpu', 24);
|
|
$ramHistory = $this->systemMetricsService->getHourlyMetrics('ram', 24);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'cpu_history' => $cpuHistory,
|
|
'ram_history' => $ramHistory,
|
|
'range' => $timeRange,
|
|
]);
|
|
}
|
|
}
|