327 lines
5.1 KiB
HTML
327 lines
5.1 KiB
HTML
```html
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Resource Manager</title>
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
|
|
<style>
|
|
|
|
body{
|
|
background:#f5f6fa;
|
|
}
|
|
|
|
.card{
|
|
margin-bottom:20px;
|
|
}
|
|
|
|
.ip{
|
|
font-size:0.9em;
|
|
}
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div class="container mt-4">
|
|
|
|
<h2>Resource Manager</h2>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
Neue Resource
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row g-2">
|
|
|
|
<div class="col">
|
|
<input id="name" class="form-control" placeholder="Name">
|
|
</div>
|
|
|
|
<div class="col">
|
|
<input id="customer" class="form-control" placeholder="Customer">
|
|
</div>
|
|
|
|
<div class="col">
|
|
<select id="status" class="form-select">
|
|
<option value="aktiv">aktiv</option>
|
|
<option value="gekündigt">gekündigt</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col">
|
|
<button class="btn btn-primary" onclick="createResource()">Create</button>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<h4>Aktive Ressourcen</h4>
|
|
<div id="activeResources"></div>
|
|
|
|
<h4 class="mt-4">Gekündigte Ressourcen</h4>
|
|
<div id="cancelledResources"></div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
|
|
const API="/resman/api";
|
|
|
|
function statusBadge(status){
|
|
|
|
if(status==="gekündigt"){
|
|
return `<span class="badge bg-dark">Gekündigt</span>`;
|
|
}
|
|
|
|
return `<span class="badge bg-success">Aktiv</span>`;
|
|
}
|
|
|
|
function renderResource(r){
|
|
|
|
return `
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="d-flex justify-content-between">
|
|
|
|
<div>
|
|
<h5>${r.name || ""}</h5>
|
|
${statusBadge(r.status)}
|
|
<br>
|
|
<small>${r.customer || ""}</small>
|
|
</div>
|
|
|
|
<div>
|
|
<button class="btn btn-sm btn-danger" onclick="deleteResource(${r.id})">
|
|
Delete
|
|
</button>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<strong>IPs</strong>
|
|
|
|
<div id="ips-${r.id}" class="mb-2"></div>
|
|
|
|
<div class="input-group input-group-sm">
|
|
|
|
<input class="form-control" placeholder="IP" id="ip-${r.id}">
|
|
|
|
<select class="form-select" id="type-${r.id}">
|
|
<option value="public">public</option>
|
|
<option value="private">private</option>
|
|
</select>
|
|
|
|
<input class="form-control" placeholder="comment" id="comment-${r.id}">
|
|
|
|
<button class="btn btn-primary" onclick="addIP(${r.id})">
|
|
Add
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
async function loadResources(){
|
|
|
|
const activeDiv=document.getElementById("activeResources");
|
|
const cancelledDiv=document.getElementById("cancelledResources");
|
|
|
|
activeDiv.innerHTML="";
|
|
cancelledDiv.innerHTML="";
|
|
|
|
try{
|
|
|
|
const res=await fetch(`${API}/resources/active`);
|
|
const active=await res.json();
|
|
|
|
active.forEach(r=>{
|
|
activeDiv.innerHTML+=renderResource(r);
|
|
|
|
setTimeout(()=>loadIPs(r.id),100);
|
|
});
|
|
|
|
}catch(e){
|
|
console.error(e);
|
|
}
|
|
|
|
try{
|
|
|
|
const res=await fetch(`${API}/resources/cancelled`);
|
|
const cancelled=await res.json();
|
|
|
|
cancelled.forEach(r=>{
|
|
cancelledDiv.innerHTML+=renderResource(r);
|
|
|
|
setTimeout(()=>loadIPs(r.id),100);
|
|
});
|
|
|
|
}catch(e){
|
|
console.error(e);
|
|
}
|
|
|
|
}
|
|
|
|
async function createResource(){
|
|
|
|
const name=document.getElementById("name").value;
|
|
const customer=document.getElementById("customer").value;
|
|
const status=document.getElementById("status").value;
|
|
|
|
await fetch(`${API}/resources`,{
|
|
method:"POST",
|
|
headers:{
|
|
"Content-Type":"application/json"
|
|
},
|
|
body:JSON.stringify({
|
|
name,
|
|
customer,
|
|
status
|
|
})
|
|
});
|
|
|
|
document.getElementById("name").value="";
|
|
document.getElementById("customer").value="";
|
|
|
|
loadResources();
|
|
|
|
}
|
|
|
|
async function deleteResource(id){
|
|
|
|
await fetch(`${API}/resources/${id}`,{
|
|
method:"DELETE"
|
|
});
|
|
|
|
async function addIP(resourceId){
|
|
|
|
const ip=document.getElementById("ip-"+resourceId).value;
|
|
const type=document.getElementById("type-"+resourceId).value;
|
|
const comment=document.getElementById("comment-"+resourceId).value;
|
|
|
|
if(!ip){
|
|
alert("IP fehlt");
|
|
return;
|
|
}
|
|
|
|
await fetch("/resman/api/resources/"+resourceId+"/ips",{
|
|
method:"POST",
|
|
headers:{
|
|
"Content-Type":"application/json"
|
|
},
|
|
body:JSON.stringify({
|
|
ip:ip,
|
|
type:type,
|
|
comment:comment
|
|
})
|
|
});
|
|
|
|
loadResources();
|
|
|
|
}
|
|
|
|
|
|
loadResources();
|
|
|
|
}
|
|
|
|
async function loadIPs(resourceId){
|
|
|
|
const container=document.getElementById("ips-"+resourceId);
|
|
|
|
const res=await fetch(`${API}/resources/${resourceId}/ips`);
|
|
const data=await res.json();
|
|
|
|
let html="";
|
|
|
|
data.forEach(ip=>{
|
|
|
|
html+=`
|
|
|
|
<div class="d-flex justify-content-between border rounded p-1 mb-1 ip">
|
|
|
|
<div>
|
|
<strong>${ip.ip}</strong>
|
|
<span class="text-muted">(${ip.type})</span>
|
|
<small>${ip.comment || ""}</small>
|
|
</div>
|
|
|
|
<button class="btn btn-sm btn-danger"
|
|
onclick="deleteIP(${ip.id},${resourceId})">
|
|
X
|
|
</button>
|
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
});
|
|
|
|
container.innerHTML=html;
|
|
|
|
}
|
|
|
|
async function addIP(resourceId){
|
|
|
|
const ip=document.getElementById("ip-"+resourceId).value;
|
|
const type=document.getElementById("type-"+resourceId).value;
|
|
const comment=document.getElementById("comment-"+resourceId).value;
|
|
|
|
await fetch(`${API}/resources/${resourceId}/ips`,{
|
|
method:"POST",
|
|
headers:{
|
|
"Content-Type":"application/json"
|
|
},
|
|
body:JSON.stringify({
|
|
ip,
|
|
type,
|
|
comment
|
|
})
|
|
});
|
|
|
|
document.getElementById("ip-"+resourceId).value="";
|
|
document.getElementById("comment-"+resourceId).value="";
|
|
|
|
loadIPs(resourceId);
|
|
|
|
}
|
|
|
|
async function deleteIP(ipId,resourceId){
|
|
|
|
await fetch(`${API}/ips/${ipId}`,{
|
|
method:"DELETE"
|
|
});
|
|
|
|
loadIPs(resourceId);
|
|
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
loadResources();
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|
|
|