Add server links management and timeout guard for VM/container discovery
All checks were successful
Build-Publish / build (linux/amd64) (push) Successful in 5s
Build-Publish / build (linux/arm64) (push) Successful in 13s
Build-Publish / create-manifest (push) Successful in 2s
Build-Publish / publish-template (push) Successful in 15s

This commit is contained in:
j
2026-03-08 20:26:07 +13:00
parent 7d7cd25518
commit d9d7662d8c
4 changed files with 200 additions and 6 deletions

View File

@@ -57,6 +57,14 @@
</div>
<div class="server-ip">{{ server.primary_ip or 'No IP' }}</div>
<div class="server-os">{% if sys.get('platform') %}{{ sys.get('platform')|capitalize }} {{ sys.get('platform_version', '') }} / {% endif %}{{ sys.get('os_pretty', '') }}</div>
{% set server_links = server.links or [] %}
{% if server_links %}
<div class="service-links" onclick="event.stopPropagation();">
{% for link in server_links %}
<a href="{{ link.url }}" class="service-link" target="_blank" rel="noopener" title="{{ link.url }}">{{ link.label }}</a>
{% endfor %}
</div>
{% endif %}
{% if server.is_online and (cpu.get('model') or mem.get('total_mb')) %}
<div class="server-hw">
{%- if cpu.get('model') %}{{ cpu.get('model') }}{% endif %}
@@ -139,6 +147,19 @@
onclick="event.stopPropagation();"
oninput="autoResizeNotes(this); debounceSaveNotes(this);">{{ server.notes or '' }}</textarea>
</div>
<div class="links-section" onclick="event.stopPropagation();">
<h4>Service Links</h4>
<div class="links-list" data-server-id="{{ server.id }}">
{% for link in server_links %}
<div class="link-row">
<input type="text" class="link-label" value="{{ link.label }}" placeholder="Label" onchange="saveLinks(this)">
<input type="text" class="link-url" value="{{ link.url }}" placeholder="https://..." onchange="saveLinks(this)">
<button class="link-remove" onclick="removeLink(this)" title="Remove">&times;</button>
</div>
{% endfor %}
</div>
<button class="link-add-btn" onclick="addLink(this, {{ server.id }})">+ Add link</button>
</div>
<div class="details-grid">
<!-- System Info -->
<div class="detail-section">
@@ -475,6 +496,45 @@
_notesTimers[id] = setTimeout(() => saveNotes(ta), 800);
}
function getLinksFromList(listEl) {
const links = [];
listEl.querySelectorAll('.link-row').forEach(row => {
const label = row.querySelector('.link-label').value.trim();
const url = row.querySelector('.link-url').value.trim();
if (label && url) links.push({label, url});
});
return links;
}
function saveLinks(el) {
const list = el.closest('.links-list');
const id = list.dataset.serverId;
const links = getLinksFromList(list);
fetch('/api/servers/' + id + '/links', {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({links})
});
}
function addLink(btn, serverId) {
const list = btn.previousElementSibling;
const row = document.createElement('div');
row.className = 'link-row';
row.innerHTML = '<input type="text" class="link-label" placeholder="Label" onchange="saveLinks(this)">' +
'<input type="text" class="link-url" placeholder="https://..." onchange="saveLinks(this)">' +
'<button class="link-remove" onclick="removeLink(this)" title="Remove">&times;</button>';
list.appendChild(row);
row.querySelector('.link-label').focus();
}
function removeLink(btn) {
const row = btn.closest('.link-row');
const list = row.closest('.links-list');
row.remove();
saveLinks(list);
}
function saveNotes(ta) {
const id = ta.dataset.serverId;
fetch('/api/servers/' + id + '/notes', {
@@ -550,6 +610,16 @@
const refreshMs = hasData ? 60000 : 5000;
setInterval(function() { location.reload(); }, refreshMs);
// Detect new backend version and auto-reload
const knownBuild = '{{ build_date }}';
setInterval(function() {
fetch('/api/version').then(r => r.json()).then(d => {
if (d.build_date && d.build_date !== knownBuild) {
location.reload();
}
}).catch(() => {});
}, 5000);
// Restore state on load
restoreExpanded();
</script>