window.resources = [] window.loadResources = async function(){ window.resources = await api(API + "/resources/active") const resources = window.resources const mappings = await api(API + "/domainmap") const table = document.getElementById("resources") table.innerHTML = "" resources.forEach(r => { let ips = "" if(Array.isArray(r.ips)){ ips = r.ips.map(ip => { const cls = (ip.type || "").toLowerCase().includes("public") ? "ip public" : "ip" return "" + (ip.type || "") + " " + ip.ip + "" }).join("") } let domains = mappings .filter(m => m.resource_id == r.id) .map(m => "🌐 " + m.domain_name + "") .join("") const tr = document.createElement("tr") tr.innerHTML = ` ${r.name} ${r.produkt || ""} ${r.provider || ""} ...
${r.cpu ? r.cpu + " CPU" : ""} ${r.ram ? " β€’ " + r.ram + " RAM" : ""} ${r.disk ? " β€’ " + r.disk : ""} ${r.os ? " β€’ " + r.os : ""}
${domains} ${ips}
` table.appendChild(tr) checkServerStatus(r) }) } window.saveResource = async function(){ const id = document.getElementById("resource_id").value let kostenMonat=document.getElementById("kosten_monat").value let kostenJahr=document.getElementById("kosten_jahr").value if(kostenMonat) kostenMonat=kostenMonat.replace(",",".") if(kostenJahr) kostenJahr=kostenJahr.replace(",",".") const data={ name:name.value, produkt:produkt.value, provider:provider.value, art:art.value, cpu:cpu.value, ram:ram.value, disk:disk.value, os:os.value, kosten_monat:kostenMonat || null, kosten_jahr:kostenJahr || null, providername:providername.value, ipv6_net:ipv6_net.value, bestelldatum:bestelldatum.value || null, kuendbar_ab:kuendbar_ab.value || null, kuendigungsdatum:kuendigungsdatum.value || null, status:status.value, bemerkung:bemerkung.value } await runAction( async () => { if(id){ await api(API+"/resources/"+id,{method:"PUT",headers:{'Content-Type':'application/json'},body:JSON.stringify(data)}) }else{ await api(API+"/resources",{method:"POST",headers:{'Content-Type':'application/json'},body:JSON.stringify(data)}) } }, async () => { closeModal() await loadResources() loadInfrastructure() loadCosts() } ) } window.deleteResource = async function(id){ if(!confirm("delete resource?")) return await runAction( async () => { await api(API+"/resources/"+id,{method:"DELETE"}) }, async () => { await loadResources() loadInfrastructure() loadCosts() } ) } window.checkServerStatus = async function(resource){ if(!Array.isArray(resource.ips)) return let ip = resource.ips.find(i => i.type?.includes("public")) || resource.ips[0] if(!ip) return try{ const res = await fetch(API+"/ping/"+ip.ip) const data = await res.json() const el = document.getElementById("status-"+resource.id) if(el){ el.innerHTML = data.status === "online" ? "🟒" : "πŸ”΄" } }catch(e){ console.log(e) } } window.loadCancelled = async function(){ const data = await api(API + "/resources/cancelled") const table = document.getElementById("cancelled") table.innerHTML = "" data.forEach(r => { const tr = document.createElement("tr") tr.innerHTML = ` ${r.name} ${r.produkt || ""} ${r.provider || ""} ${r.cpu || ""} ${r.ram || ""} ${r.disk || ""} ${r.status || ""} ` table.appendChild(tr) }) } window.saveIP = async function(){ const resourceId = document.getElementById("ip_resource_id").value const ipField = document.getElementById("new_ip") const id = ipField.dataset.editId const ip = ipField.value const type = document.getElementById("new_type").value const comment = document.getElementById("new_comment").value await runAction( async () => { if(id){ await api(API + "/ips/" + id, { method: "PUT", headers: {'Content-Type':'application/json'}, body: JSON.stringify({ip, type, comment}) }) delete ipField.dataset.editId }else{ try{ const result = await api(API + "/ipcheck/" + ip, {}, { showError: false }) if(result.length){ if(!confirm("IP existiert bereits. Trotzdem speichern?")){ const error = new Error("IP save cancelled") error.silent = true throw error } } }catch(e){ if(e.silent) throw e console.warn("IP check fehlgeschlagen", e) } await api(API + "/resources/" + resourceId + "/ips", { method: "POST", headers: {'Content-Type':'application/json'}, body: JSON.stringify({ip, type, comment}) }) } }, async () => { ipField.value = "" document.getElementById("new_type").value = "" document.getElementById("new_comment").value = "" await loadIPs(resourceId) await loadResources() loadInfrastructure() cancelIPEdit() } ) } window.deleteIP = async function(id, resourceId){ if(!confirm("IP lΓΆschen?")) return await runAction( async () => { await api(API + "/ips/" + id, { method: "DELETE" }) }, async () => { await loadIPs(resourceId) await loadResources() loadInfrastructure() } ) } window.loadIPs = async function(resourceId){ const ips = await api(API + "/resources/" + resourceId + "/ips") const container = document.getElementById("ipList") container.innerHTML = "" ips.forEach(ip => { // βœ… HIER rein! const cls = (ip.type || "").toLowerCase().includes("public") ? "ip public" : "ip" const div = document.createElement("div") div.innerHTML = ` ${ip.ip} (${ip.type || ""}) ${ip.comment || ""} ` container.appendChild(div) }) } window.editIP = function(id, ip, type, comment){ document.getElementById("new_ip").value = ip document.getElementById("new_type").value = type document.getElementById("new_comment").value = comment document.getElementById("new_ip").dataset.editId = id // πŸ‘‡ UX Highlight + Fokus document.getElementById("ipForm").classList.add("edit-mode") document.getElementById("ipSaveBtn").innerText = "Update" document.getElementById("ipCancelBtn").style.display = "inline-block" document.getElementById("new_ip").focus() // πŸ‘ˆ HIER } window.cancelIPEdit = function(){ const ipField = document.getElementById("new_ip") delete ipField.dataset.editId ipField.value = "" document.getElementById("new_type").value = "" document.getElementById("new_comment").value = "" document.getElementById("ipForm").classList.remove("edit-mode") document.getElementById("ipSaveBtn").innerText = "Add" document.getElementById("ipCancelBtn").style.display = "none" } window.moveResource = async function(id, direction){ await runAction( async () => { await api(API + "/resources/" + id + "/move", { method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ direction }) }) }, async () => { await loadResources() loadInfrastructure() loadCosts() } ) }