Show each container's fallback tier on the Monitor board
The row's left border carries it rather than the status dot, which already means running or stopped.
This commit is contained in:
@@ -1341,8 +1341,11 @@ code.vv-unknown-var { color: #ff9800; background: #1f130d; }
|
|||||||
.vv-df-fname { flex: 1; font-size: 12px; color: #aaa; font-weight: 500;
|
.vv-df-fname { flex: 1; font-size: 12px; color: #aaa; font-weight: 500;
|
||||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||||
.vv-df-folder-body { padding-left: 10px; padding-bottom: 3px; }
|
.vv-df-folder-body { padding-left: 10px; padding-bottom: 3px; }
|
||||||
.vv-df-container { display: flex; align-items: center; gap: 7px; padding: 3px 6px;
|
/* padding-left is 4px against a 2px border so a container with no fallback tier still lines up
|
||||||
cursor: pointer; border-radius: 3px; user-select: none; }
|
with one that has a stripe — the border is always present, only its colour changes. */
|
||||||
|
.vv-df-container { display: flex; align-items: center; gap: 7px; padding: 3px 6px 3px 4px;
|
||||||
|
cursor: pointer; border-radius: 3px; user-select: none;
|
||||||
|
border-left: 2px solid transparent; }
|
||||||
.vv-df-container:hover { background: rgba(255,255,255,0.04); }
|
.vv-df-container:hover { background: rgba(255,255,255,0.04); }
|
||||||
.vv-df-active { background: rgba(100,149,237,0.1) !important;
|
.vv-df-active { background: rgba(100,149,237,0.1) !important;
|
||||||
outline: 1px solid rgba(100,149,237,0.35);
|
outline: 1px solid rgba(100,149,237,0.35);
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
//
|
//
|
||||||
// EXPORTS
|
// EXPORTS
|
||||||
// vv_container_webui() WebUI URL for one container, or empty
|
// vv_container_webui() WebUI URL for one container, or empty
|
||||||
// vv_get_docker_folders() folder grouping in the legacy shape
|
// vv_container_tier_map() container name (lowercased) => fallback tier 1-4
|
||||||
|
// vv_get_docker_folders() folder grouping in the legacy shape, each container carrying 'tier'
|
||||||
//
|
//
|
||||||
// CONFIGURATION
|
// CONFIGURATION
|
||||||
// Inherits everything from docker.php — see that file's CONFIGURATION block.
|
// Inherits everything from docker.php — see that file's CONFIGURATION block.
|
||||||
@@ -54,11 +55,31 @@ function vv_container_webui(string $name, array $portMap): string {
|
|||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback tier for each container, from FALLBACK_<ME>_TIER1..4 in THIS host's own conf —
|
||||||
|
// that list is what the partner starts for us, so a lower tier means it comes back sooner.
|
||||||
|
// Keyed lowercase because conf spelling and docker's spelling of a name need not match.
|
||||||
|
function vv_container_tier_map(): array {
|
||||||
|
$me = strtoupper(vv_detect_host());
|
||||||
|
if ($me === 'UNKNOWN') return [];
|
||||||
|
$raw = vv_read_host_conf_raw(strtolower($me));
|
||||||
|
if ($raw === '') return [];
|
||||||
|
|
||||||
|
$map = [];
|
||||||
|
for ($t = 1; $t <= 4; $t++) {
|
||||||
|
foreach (vv_parse_conf_list($raw, "FALLBACK_{$me}_TIER{$t}") as $name) {
|
||||||
|
$key = strtolower(trim($name));
|
||||||
|
if ($key !== '' && !isset($map[$key])) $map[$key] = $t; // lowest tier wins a duplicate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $map;
|
||||||
|
}
|
||||||
|
|
||||||
function vv_get_docker_folders(): array {
|
function vv_get_docker_folders(): array {
|
||||||
// Varaverk's own docker_folders.json is the primary store (see include/docker.php) —
|
// Varaverk's own docker_folders.json is the primary store (see include/docker.php) —
|
||||||
// reading folder.view3's mirror directly here left this widget empty on any host
|
// reading folder.view3's mirror directly here left this widget empty on any host
|
||||||
// without that optional third-party plugin installed.
|
// without that optional third-party plugin installed.
|
||||||
$folderData = vv_dk_read_json();
|
$folderData = vv_dk_read_json();
|
||||||
|
$tierMap = vv_container_tier_map();
|
||||||
|
|
||||||
// One docker ps call: names, status, port mappings
|
// One docker ps call: names, status, port mappings
|
||||||
$raw = shell_exec("docker ps -a --format '{{.Names}}\t{{.Status}}\t{{.Ports}}' 2>/dev/null") ?? '';
|
$raw = shell_exec("docker ps -a --format '{{.Names}}\t{{.Status}}\t{{.Ports}}' 2>/dev/null") ?? '';
|
||||||
@@ -92,6 +113,7 @@ function vv_get_docker_folders(): array {
|
|||||||
'running' => $running,
|
'running' => $running,
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
'webui' => vv_container_webui($cname, $portMap),
|
'webui' => vv_container_webui($cname, $portMap),
|
||||||
|
'tier' => $tierMap[strtolower($cname)] ?? null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
usort($containers, fn($a, $b) => $b['running'] <=> $a['running'] ?: strcmp($a['name'], $b['name']));
|
usort($containers, fn($a, $b) => $b['running'] <=> $a['running'] ?: strcmp($a['name'], $b['name']));
|
||||||
@@ -114,6 +136,7 @@ function vv_get_docker_folders(): array {
|
|||||||
'running' => $running,
|
'running' => $running,
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
'webui' => vv_container_webui($cname, $portMap),
|
'webui' => vv_container_webui($cname, $portMap),
|
||||||
|
'tier' => $tierMap[strtolower($cname)] ?? null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
usort($ungrouped, fn($a, $b) => strcmp($a['name'], $b['name']));
|
usort($ungrouped, fn($a, $b) => strcmp($a['name'], $b['name']));
|
||||||
|
|||||||
@@ -2975,6 +2975,12 @@ function vvRenderDockerFolders(data) {
|
|||||||
const stateColor = s => ({ running:'#4caf50', paused:'#ff9800' })[s] ?? '#444';
|
const stateColor = s => ({ running:'#4caf50', paused:'#ff9800' })[s] ?? '#444';
|
||||||
const stateLabel = s => ({ running:'Running', paused:'Paused', 'shut off':'Off', crashed:'Crashed' })[s] ?? s;
|
const stateLabel = s => ({ running:'Running', paused:'Paused', 'shut off':'Off', crashed:'Crashed' })[s] ?? s;
|
||||||
|
|
||||||
|
// Fallback tier stripe. Warm (comes back immediately) to cool (waits 24h), riding the row's
|
||||||
|
// left border rather than the status dot — the dot already means running vs stopped, and
|
||||||
|
// overloading it would make a stopped tier-1 container indistinguishable from a running one.
|
||||||
|
const tierColor = t => ({ 1:'#ff5252', 2:'#ffa726', 3:'#ffd54f', 4:'#4fc3f7' })[t] ?? '';
|
||||||
|
const tierWhen = t => ({ 1:'immediately', 2:'after 4h', 3:'after 12h', 4:'after 24h' })[t] ?? '';
|
||||||
|
|
||||||
// ── VMs section ─────────────────────────────────────────────────────────────
|
// ── VMs section ─────────────────────────────────────────────────────────────
|
||||||
let html = '';
|
let html = '';
|
||||||
const vms = data.vms?.vms ?? [];
|
const vms = data.vms?.vms ?? [];
|
||||||
@@ -3033,7 +3039,14 @@ function vvRenderDockerFolders(data) {
|
|||||||
class="vv-btn-sm vv-edit-btn">✎ Edit</button>
|
class="vv-btn-sm vv-edit-btn">✎ Edit</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
return `<div class="vv-df-container${active ? ' vv-df-active' : ''}"
|
// Tier arrives as an int from conf, but it is still payload — anything outside 1-4 gets no
|
||||||
|
// stripe rather than being interpolated into the style attribute.
|
||||||
|
const tNum = Number(c.tier);
|
||||||
|
const tOk = Number.isInteger(tNum) && tNum >= 1 && tNum <= 4;
|
||||||
|
const tSty = tOk ? ` style="border-left-color:${tierColor(tNum)};"` : '';
|
||||||
|
const tTip = tOk ? ` title="Fallback tier ${tNum} — partner starts this ${tierWhen(tNum)}"` : '';
|
||||||
|
|
||||||
|
return `<div class="vv-df-container${active ? ' vv-df-active' : ''}"${tSty}${tTip}
|
||||||
onclick="event.stopPropagation();vvToggleContainer('${sn}')">
|
onclick="event.stopPropagation();vvToggleContainer('${sn}')">
|
||||||
<span class="vv-df-dot" style="background:${dot};${pulse}"></span>
|
<span class="vv-df-dot" style="background:${dot};${pulse}"></span>
|
||||||
<span class="vv-df-cname">${vvEscHtml(c.name)}</span>
|
<span class="vv-df-cname">${vvEscHtml(c.name)}</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user