diff --git a/app/Services/ServerCanvas.php b/app/Services/ServerCanvas.php index d822920a54..5539c481c3 100644 --- a/app/Services/ServerCanvas.php +++ b/app/Services/ServerCanvas.php @@ -65,6 +65,23 @@ class ServerCanvas ->reject(fn (Environment $environment) => $used->has($environment->id)) ->map(fn (Environment $environment) => $this->canvas->emptyNode($environment->project, $environment, $zoneOf($environment->project), $environment->project->name.' / '.$environment->name, $canEdit)) ->values(); + // The canvas draws a zone around its cards, so a server without cards gets a placeholder card. + $filled = $nodes->concat($empty)->pluck('zone')->flip(); + $bare = $servers->reject(fn (Server $server) => $filled->has($server->uuid))->map(fn (Server $server) => [ + 'id' => 'empty-server:'.$server->uuid, + 'type' => 'empty', + 'name' => 'No resources yet', + 'subtitle' => 'Open to see this server', + 'status' => null, + 'zone' => $server->uuid, + 'extra_zones' => [], + 'urls' => [], + 'children' => [], + 'link' => route('server.show', ['server_uuid' => $server->uuid]), + 'context' => null, + 'project' => null, + 'environment' => null, + ])->values(); return [ 'title' => $single ? $single->name : 'Servers', @@ -80,7 +97,7 @@ class ServerCanvas 'zones' => $servers->map(fn (Server $server) => [...$this->canvas->zone($server, $canReadSensitive), 'details' => $this->details($server)]) ->when($empty->contains('zone', EnvironmentCanvas::EMPTY_ZONE), fn (Collection $zones) => $zones->push($this->canvas->emptyZone())) ->values()->all(), - 'nodes' => $nodes->concat($empty)->all(), + 'nodes' => $nodes->concat($empty)->concat($bare)->all(), 'links' => collect($graph['links'])->filter(fn (array $link) => $shown->has($link['source']) && $shown->has($link['target']))->values()->all(), 'positions' => [], ]; diff --git a/tests/Feature/ServerCanvasTest.php b/tests/Feature/ServerCanvasTest.php index cf8bd8878e..58de97837d 100644 --- a/tests/Feature/ServerCanvasTest.php +++ b/tests/Feature/ServerCanvasTest.php @@ -105,6 +105,24 @@ test('the servers canvas puts empty environments of a project without resources ->and(collect($response->json('nodes'))->where('project.uuid', $bare->uuid)->pluck('zone')->all())->toBe([$this->db->uuid]); }); +test('the servers canvas shows a server without resources as a placeholder card in its zone', function () { + serverCanvasApp($this->environment, $this->web, 'storefront'); + Environment::query()->where('project_id', $this->project->id)->where('name', '!=', 'staging')->delete(); + + $response = serverCanvasSession($this, $this->admin, $this->team) + ->getJson('/canvas/api/servers/canvas') + ->assertOk(); + + $placeholder = collect($response->json('nodes'))->firstWhere('zone', $this->db->uuid); + + expect($placeholder)->toMatchArray([ + 'id' => 'empty-server:'.$this->db->uuid, + 'type' => 'empty', + 'name' => 'No resources yet', + 'link' => route('server.show', ['server_uuid' => $this->db->uuid]), + ])->and(collect($response->json('nodes'))->where('zone', $this->web->uuid)->pluck('name')->all())->toBe(['storefront']); +}); + test('one server canvas shows only that server, and links that leave it are hidden', function () { $app = serverCanvasApp($this->environment, $this->web, 'storefront'); $api = serverCanvasApp($this->environment, $this->db, 'orders-api');