Add server links management and timeout guard for VM/container discovery
This commit is contained in:
@@ -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">×</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">×</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>
|
||||
|
||||
Reference in New Issue
Block a user