mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(canvas): fit the server header and skip placeholder cards in the status summary
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c4bc9ae8bf
commit
44c6322259
@@ -59,7 +59,7 @@
|
||||
{#if zone.ip}
|
||||
<button
|
||||
type="button"
|
||||
class="truncate font-mono text-[11px] text-neutral-400 hover:text-neutral-600 dark:text-fg-faint dark:hover:text-fg-dim"
|
||||
class="shrink-0 font-mono text-[11px] text-neutral-400 hover:text-neutral-600 dark:text-fg-faint dark:hover:text-fg-dim"
|
||||
title={showIp ? 'Hide IP address' : 'Show IP address'}
|
||||
onpointerdown={e => e.stopPropagation()}
|
||||
onclick={() => (showIp = !showIp)}
|
||||
|
||||
@@ -12,6 +12,7 @@ export const ZONE_GAP = 72;
|
||||
export const ZONE_PADDING = 24;
|
||||
export const ZONE_HEADER = 40;
|
||||
export const SERVER_ZONE_HEADER = 68; // server canvas: a second header row with host facts, proxy and usage
|
||||
export const SERVER_ZONE_MIN_WIDTH = 560; // server canvas: room for the header (name, IP, status, host facts) above one card
|
||||
export const MAX_CHILDREN = 5;
|
||||
export const MAX_ROWS = 6; // auto placement wraps a type into another column after this many cards
|
||||
export const NO_SERVER = 'No server';
|
||||
@@ -414,7 +415,7 @@ export function zoneBoxes(graph, positions, sizes = {}) {
|
||||
nodes: group.nodes.map(n => n.id),
|
||||
x: minX - ZONE_PADDING,
|
||||
y: minY - ZONE_PADDING - zoneHeader(group.zone),
|
||||
width: maxX - minX + ZONE_PADDING * 2,
|
||||
width: Math.max(maxX - minX + ZONE_PADDING * 2, group.zone?.details ? SERVER_ZONE_MIN_WIDTH : 0),
|
||||
height: maxY - minY + ZONE_PADDING * 2 + zoneHeader(group.zone),
|
||||
});
|
||||
}
|
||||
@@ -541,10 +542,10 @@ export function fitView(bounds, area, readable = false) {
|
||||
return { z, x: x - bounds.minX * z, y: y - bounds.minY * z };
|
||||
}
|
||||
|
||||
/** Resource cards per status tone ({ok, warn, bad, busy, idle}); unmanaged containers are not counted. */
|
||||
/** Resource cards per status tone ({ok, warn, bad, busy, idle}); unmanaged containers and placeholder cards are not counted. */
|
||||
export function statusSummary(nodes) {
|
||||
const out = { ok: 0, warn: 0, bad: 0, busy: 0, idle: 0 };
|
||||
for (const n of nodes || []) if (n.type !== 'container' && !isSource(n)) out[statusTone(n.status)]++;
|
||||
for (const n of nodes || []) if (n.type !== 'container' && n.type !== 'empty' && !isSource(n)) out[statusTone(n.status)]++;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
MAX_ROWS,
|
||||
COLUMN_GAP,
|
||||
ROW_GAP,
|
||||
SERVER_ZONE_MIN_WIDTH,
|
||||
ZONE_HEADER,
|
||||
ZONE_PADDING,
|
||||
ZONE_GAP,
|
||||
@@ -130,6 +131,13 @@ test('zone boxes wrap their cards with padding and header', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('server canvas zone boxes are wide enough for their header, also with one card', () => {
|
||||
const g = graph([node('a', 'application', 's1')], { zones: [{ id: 's1', name: 'One', details: {} }] });
|
||||
const [box] = zoneBoxes(g, { a: { x: 0, y: 0 } }, { a: { width: 260, height: 100 } });
|
||||
assert.equal(box.x, -ZONE_PADDING);
|
||||
assert.equal(box.width, SERVER_ZONE_MIN_WIDTH);
|
||||
});
|
||||
|
||||
test('zone boxes skip zones without cards', () => {
|
||||
assert.deepEqual(zoneBoxes(graph([node('a', 'application', 's2')]), { a: { x: 0, y: 0 } }).map(b => b.id), ['s2']);
|
||||
});
|
||||
@@ -385,12 +393,13 @@ test('server view: saved groups of different environments that would overlap are
|
||||
assert.ok(Math.abs(p.x - s.x) >= CARD_WIDTH || Math.abs(p.y - s.y) >= estimateNodeHeight(g.nodes[0]), 'the groups do not cover each other');
|
||||
});
|
||||
|
||||
test('status summary counts resources by tone, without unmanaged containers', () => {
|
||||
test('status summary counts resources by tone, without unmanaged containers and placeholder cards', () => {
|
||||
const nodes = [
|
||||
node('a', 'application', 'z', { status: 'running:healthy' }),
|
||||
node('b', 'database', 'z', { status: 'exited:unhealthy' }),
|
||||
node('c', 'service', 'z', { status: 'exited' }),
|
||||
node('container:1', 'container', 'z', { status: 'exited' }),
|
||||
node('empty:1', 'empty', 'z', { status: null }),
|
||||
];
|
||||
assert.deepEqual(statusSummary(nodes), { ok: 1, warn: 0, bad: 2, busy: 0, idle: 0 });
|
||||
assert.equal(statusWord('exited:unhealthy'), 'Exited');
|
||||
|
||||
Reference in New Issue
Block a user