2026-06-15 21:09:49 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\V5;
|
|
|
|
|
|
2026-06-19 09:44:42 +00:00
|
|
|
use App\Events\V5RealtimeTestEvent;
|
2026-06-15 21:09:49 +00:00
|
|
|
use App\Http\Controllers\Controller;
|
2026-07-06 15:40:37 +00:00
|
|
|
use App\Http\Controllers\V5\Concerns\ResolvesCurrentTeam;
|
|
|
|
|
use App\Http\Controllers\V5\Concerns\ResolvesProjectSelection;
|
|
|
|
|
use App\Http\Controllers\V5\Concerns\SerializesCanvasResources;
|
2026-06-16 17:38:21 +00:00
|
|
|
use App\Models\Project;
|
2026-06-15 21:09:49 +00:00
|
|
|
use App\Models\Team;
|
2026-06-20 07:23:16 +00:00
|
|
|
use App\Models\V5\Application as V5Application;
|
|
|
|
|
use App\Models\V5\ResourceConnection;
|
2026-06-16 13:45:16 +00:00
|
|
|
use App\Models\V5\Server as V5Server;
|
2026-06-15 21:09:49 +00:00
|
|
|
use App\Services\Flux\FluxHealth;
|
2026-07-06 15:40:37 +00:00
|
|
|
use App\Support\V5\ResourceConnectionSerializer;
|
2026-06-16 17:38:21 +00:00
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
2026-06-16 11:57:42 +00:00
|
|
|
use Illuminate\Http\JsonResponse;
|
2026-06-15 21:09:49 +00:00
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
use Inertia\Inertia;
|
|
|
|
|
use Inertia\Response;
|
|
|
|
|
|
2026-06-16 20:23:50 +00:00
|
|
|
class DashboardController extends Controller
|
2026-06-15 21:09:49 +00:00
|
|
|
{
|
2026-07-06 15:40:37 +00:00
|
|
|
use ResolvesCurrentTeam;
|
|
|
|
|
use ResolvesProjectSelection;
|
|
|
|
|
use SerializesCanvasResources;
|
2026-06-21 20:39:16 +00:00
|
|
|
|
2026-07-06 15:40:37 +00:00
|
|
|
public function __construct(private readonly ResourceConnectionSerializer $connectionSerializer) {}
|
2026-06-16 17:38:21 +00:00
|
|
|
|
2026-06-15 21:09:49 +00:00
|
|
|
public function __invoke(Request $request, FluxHealth $fluxHealth): Response
|
|
|
|
|
{
|
|
|
|
|
$currentTeam = $request->attributes->get('v5.currentTeam');
|
2026-06-16 17:38:21 +00:00
|
|
|
$projects = $this->projects($currentTeam);
|
|
|
|
|
[$selectedProject, $selectedEnvironment] = $this->selectedProjectAndEnvironment($request, $projects);
|
2026-07-18 13:55:47 +00:00
|
|
|
$applications = $this->applications($currentTeam, $selectedProject, $selectedEnvironment);
|
|
|
|
|
$requestedApplicationUuid = $request->query('application');
|
|
|
|
|
$selectedApplicationUuid = collect($applications)->contains(
|
|
|
|
|
fn (array $application): bool => $application['id'] === $requestedApplicationUuid
|
|
|
|
|
) ? $requestedApplicationUuid : null;
|
2026-06-15 21:09:49 +00:00
|
|
|
|
2026-06-16 20:23:50 +00:00
|
|
|
return Inertia::render('Dashboard', [
|
2026-06-20 07:23:16 +00:00
|
|
|
'currentTeam' => $this->serializeCurrentTeam($currentTeam),
|
2026-06-15 21:09:49 +00:00
|
|
|
'flux' => $fluxHealth->check(),
|
2026-07-18 13:55:47 +00:00
|
|
|
'applications' => $applications,
|
2026-06-20 07:23:16 +00:00
|
|
|
'caddyIngresses' => $this->caddyIngresses($currentTeam),
|
|
|
|
|
'resourceConnections' => $this->resourceConnections($currentTeam, $selectedProject, $selectedEnvironment),
|
|
|
|
|
'nginxServers' => $this->nginxServers($currentTeam),
|
2026-06-16 17:38:21 +00:00
|
|
|
'projects' => $projects,
|
|
|
|
|
'selectedProjectUuid' => $selectedProject['uuid'] ?? null,
|
|
|
|
|
'selectedEnvironmentUuid' => $selectedEnvironment['uuid'] ?? null,
|
2026-07-18 13:55:47 +00:00
|
|
|
'selectedApplicationUuid' => $selectedApplicationUuid,
|
2026-06-15 21:09:49 +00:00
|
|
|
]);
|
|
|
|
|
}
|
2026-06-16 09:39:36 +00:00
|
|
|
|
2026-06-19 09:44:42 +00:00
|
|
|
public function realtimeTest(Request $request): Response
|
|
|
|
|
{
|
2026-07-06 15:40:37 +00:00
|
|
|
$currentTeam = $this->currentTeamOrFail($request);
|
2026-06-19 09:44:42 +00:00
|
|
|
|
|
|
|
|
return Inertia::render('RealtimeTest', [
|
|
|
|
|
'currentTeam' => [
|
|
|
|
|
'id' => $currentTeam->id,
|
|
|
|
|
],
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function broadcastRealtimeTest(Request $request): JsonResponse
|
|
|
|
|
{
|
2026-07-06 15:40:37 +00:00
|
|
|
$currentTeam = $this->currentTeamOrFail($request);
|
2026-06-19 09:44:42 +00:00
|
|
|
|
|
|
|
|
$validated = $request->validate([
|
|
|
|
|
'message' => ['nullable', 'string', 'max:255'],
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
V5RealtimeTestEvent::dispatch(
|
|
|
|
|
$currentTeam->id,
|
|
|
|
|
$validated['message'] ?? 'Manual v5 realtime test'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'message' => 'Realtime test event broadcasted.',
|
|
|
|
|
], 202);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 17:38:21 +00:00
|
|
|
public function updateSelection(Request $request): \Illuminate\Http\Response
|
|
|
|
|
{
|
2026-07-06 15:40:37 +00:00
|
|
|
$currentTeam = $this->currentTeamOrFail($request);
|
2026-06-16 17:38:21 +00:00
|
|
|
|
|
|
|
|
$validated = $request->validate([
|
|
|
|
|
'project_uuid' => ['required', 'string'],
|
|
|
|
|
'environment_uuid' => ['nullable', 'string'],
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$project = $this->projectQuery($currentTeam)
|
|
|
|
|
->where('uuid', $validated['project_uuid'])
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
if (! $project instanceof Project) {
|
|
|
|
|
abort(403);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$environment = $this->selectedEnvironment($project, $validated['environment_uuid'] ?? null);
|
|
|
|
|
|
|
|
|
|
$request->session()->put([
|
|
|
|
|
self::SELECTED_PROJECT_SESSION_KEY => $project->uuid,
|
|
|
|
|
self::SELECTED_ENVIRONMENT_SESSION_KEY => $environment?->uuid,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return response()->noContent();
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-06 15:40:37 +00:00
|
|
|
/**
|
|
|
|
|
* @return array<int, array<string, mixed>>
|
|
|
|
|
*/
|
|
|
|
|
private function applications(mixed $currentTeam, ?array $selectedProject, ?array $selectedEnvironment): array
|
2026-06-20 07:23:16 +00:00
|
|
|
{
|
2026-07-06 15:40:37 +00:00
|
|
|
if (! $currentTeam instanceof Team || $selectedProject === null || $selectedEnvironment === null) {
|
|
|
|
|
return [];
|
2026-06-20 07:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
2026-07-06 15:40:37 +00:00
|
|
|
return $this->applicationQuery($currentTeam, $selectedProject, $selectedEnvironment)
|
2026-06-20 07:23:16 +00:00
|
|
|
->with('server')
|
2026-07-06 15:40:37 +00:00
|
|
|
->orderBy('created_at')
|
2026-06-20 07:23:16 +00:00
|
|
|
->get()
|
2026-07-06 15:40:37 +00:00
|
|
|
->map(fn (V5Application $application) => $this->serializeApplication($application))
|
|
|
|
|
->all();
|
2026-06-20 07:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
2026-07-06 15:40:37 +00:00
|
|
|
/**
|
|
|
|
|
* @return array<int, array<string, mixed>>
|
|
|
|
|
*/
|
|
|
|
|
private function resourceConnections(mixed $currentTeam, ?array $selectedProject, ?array $selectedEnvironment): array
|
2026-06-20 07:23:16 +00:00
|
|
|
{
|
2026-07-06 15:40:37 +00:00
|
|
|
if (! $currentTeam instanceof Team || $selectedProject === null || $selectedEnvironment === null) {
|
|
|
|
|
return [];
|
2026-06-20 07:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
2026-07-06 15:40:37 +00:00
|
|
|
return ResourceConnection::query()
|
|
|
|
|
->where('team_id', $currentTeam->id)
|
|
|
|
|
->whereHas('project', fn (Builder $query) => $query
|
|
|
|
|
->where('team_id', $currentTeam->id)
|
|
|
|
|
->where('uuid', $selectedProject['uuid']))
|
|
|
|
|
->whereHas('environment', fn (Builder $query) => $query
|
|
|
|
|
->where('uuid', $selectedEnvironment['uuid']))
|
|
|
|
|
->with('rules')
|
|
|
|
|
->orderBy('id')
|
|
|
|
|
->get()
|
|
|
|
|
->map(fn (ResourceConnection $connection) => $this->connectionSerializer->serialize($connection))
|
|
|
|
|
->all();
|
2026-06-20 07:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
2026-07-06 15:40:37 +00:00
|
|
|
private function nginxServers(mixed $currentTeam): array
|
2026-06-20 07:23:16 +00:00
|
|
|
{
|
|
|
|
|
if (! $currentTeam instanceof Team) {
|
2026-07-06 15:40:37 +00:00
|
|
|
return [];
|
2026-06-20 07:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
2026-07-06 15:40:37 +00:00
|
|
|
return V5Server::query()
|
2026-06-19 05:23:45 +00:00
|
|
|
->where('team_id', $currentTeam->id)
|
2026-07-06 15:40:37 +00:00
|
|
|
->orderByRaw('last_bootstrapped_at is null')
|
2026-06-19 05:23:45 +00:00
|
|
|
->orderBy('name')
|
2026-07-06 15:40:37 +00:00
|
|
|
->get(['id', 'uuid', 'name', 'host', 'status'])
|
|
|
|
|
->map(fn (V5Server $server) => [
|
2026-07-02 19:26:41 +00:00
|
|
|
'id' => $server->uuid,
|
2026-06-16 18:52:38 +00:00
|
|
|
'name' => $server->name,
|
|
|
|
|
'host' => $server->host,
|
|
|
|
|
'status' => $server->status,
|
2026-06-16 17:38:21 +00:00
|
|
|
])
|
|
|
|
|
->all();
|
|
|
|
|
}
|
2026-06-15 21:09:49 +00:00
|
|
|
}
|