This commit is contained in:
jarek committed 2026-03-13 08:22:46 +01:00
1 parent 790ce092ee
commit 55f3101a19
51 files changed
+763 -599

No files matched your search

@@ -307,7 +307,21 @@
* Strip protocol and port from a host/IP string
*/
function stripHostProtocol(value: string): string {
return value.replace(/^(?:\w+:\/\/)/, '').replace(/[:/].*$/, '');
// Strip protocol prefix (e.g., tcp://, https://)
const stripped = value.replace(/^(?:\w+:\/\/)/, '');
// Handle bracketed IPv6 with optional port: [::1]:port → ::1
if (stripped.startsWith('[')) {
return stripped.replace(/^\[([^\]]+)\].*$/, '$1');
}
// Handle plain IPv6 (2+ colons = IPv6, not IPv4:port or hostname:port)
if ((stripped.match(/:/g) || []).length > 1) {
return stripped;
}
// IPv4 or hostname: strip :port and path
return stripped.replace(/[:/].*$/, '');
}
/**
@@ -215,28 +215,26 @@
testingAll = true;
// Process environments sequentially to avoid overwhelming the system
// This is especially important for Edge environments that have longer timeouts
for (const env of environments) {
// Mark this environment as testing
testingEnvs.add(env.id);
testingEnvs = new Set(testingEnvs);
// Show all spinners immediately, then test all envs in parallel.
// Sequential testing was wrong for edge envs: 30s timeout × N envs = N×30s total wait.
// Parallel: all timeouts run concurrently, total wait is max(individual timeouts) = 30s.
environments.forEach(env => testingEnvs.add(env.id));
testingEnvs = new Set(testingEnvs);
try {
const response = await fetch(`/api/environments/${env.id}/test`, {
method: 'POST'
});
const result = await response.json();
testResults[env.id] = result;
} catch (error) {
testResults[env.id] = { success: false, error: 'Connection failed' };
}
testResults = { ...testResults };
// Mark this environment as done
testingEnvs.delete(env.id);
testingEnvs = new Set(testingEnvs);
}
await Promise.all(
environments.map(async (env) => {
try {
const response = await fetch(`/api/environments/${env.id}/test`, { method: 'POST' });
testResults[env.id] = await response.json();
} catch {
testResults[env.id] = { success: false, error: 'Connection failed' };
} finally {
testingEnvs.delete(env.id);
testingEnvs = new Set(testingEnvs);
}
testResults = { ...testResults };
})
);
testingAll = false;
}
@@ -19,6 +19,7 @@
let confirmDestructive = $derived($appSettings.confirmDestructive);
let showStoppedContainers = $derived($appSettings.showStoppedContainers);
let highlightUpdates = $derived($appSettings.highlightUpdates);
let compactPorts = $derived($appSettings.compactPorts);
let timeFormat = $derived($appSettings.timeFormat);
let dateFormat = $derived($appSettings.dateFormat);
let downloadFormat = $derived($appSettings.downloadFormat);
@@ -178,6 +179,20 @@
</div>
<p class="text-xs text-muted-foreground">Highlight container rows in amber when updates are available</p>
</div>
<div class="space-y-1">
<div class="flex items-center gap-3">
<Label>Compact port display</Label>
<TogglePill
checked={compactPorts}
onchange={() => {
appSettings.setCompactPorts(!compactPorts);
toast.success(compactPorts ? 'Showing all ports' : 'Compact port display enabled');
}}
disabled={!$canAccess('settings', 'edit')}
/>
</div>
<p class="text-xs text-muted-foreground">Show first port with +N count instead of all ports</p>
</div>
<div class="space-y-1">
<div class="flex items-center gap-3">
<Label>Time format</Label>