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()
}
)
}