vor subdomain UX anpassung
This commit is contained in:
@@ -66,14 +66,29 @@ infra.js
|
|||||||
```bash
|
```bash
|
||||||
git clone <repo>
|
git clone <repo>
|
||||||
cd resman
|
cd resman
|
||||||
cd backend
|
docker compose up -d --build
|
||||||
npm install
|
|
||||||
npm run migrate
|
|
||||||
npm start
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 2. Migrationen
|
||||||
|
|
||||||
Beim Start des Backends werden ausstehende Migrationen automatisch ausgefuehrt.
|
Beim Start des Backends werden ausstehende Migrationen automatisch ausgefuehrt.
|
||||||
Manuell kannst du sie jederzeit mit `npm run migrate` im `backend`-Ordner starten.
|
|
||||||
|
Manuell kannst du sie im Container jederzeit starten:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose exec backend npm run migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Backend neu bauen / neu starten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build backend
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Erreichbarkeit
|
||||||
|
|
||||||
|
- Frontend/API intern: `http://127.0.0.1:3000/resman/`
|
||||||
|
- Fuer produktive Nutzung ist ein Reverse Proxy davor vorgesehen
|
||||||
|
|
||||||
|
|
||||||
🗄️ Datenbank Schema
|
🗄️ Datenbank Schema
|
||||||
|
|||||||
@@ -123,6 +123,12 @@ input, textarea {
|
|||||||
background: #f4f4f4;
|
background: #f4f4f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-meta{
|
||||||
|
font-size:13px;
|
||||||
|
color:#64748b;
|
||||||
|
margin:-6px 0 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.subdomain{
|
.subdomain{
|
||||||
@@ -225,3 +231,7 @@ body.dark .ip.public{
|
|||||||
background:#16a34a;
|
background:#16a34a;
|
||||||
color:white;
|
color:white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.dark .modal-meta{
|
||||||
|
color:#94a3b8;
|
||||||
|
}
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ Domains jährlich: <span id="costDomain">0</span> €<br>
|
|||||||
<div id="domainModal" class="modal">
|
<div id="domainModal" class="modal">
|
||||||
|
|
||||||
<h3 id="domainModalTitle">Domain</h3>
|
<h3 id="domainModalTitle">Domain</h3>
|
||||||
|
<div id="domainModalMeta" class="modal-meta"></div>
|
||||||
|
|
||||||
<input type="hidden" id="domain_id">
|
<input type="hidden" id="domain_id">
|
||||||
|
|
||||||
@@ -277,7 +278,7 @@ Domains jährlich: <span id="costDomain">0</span> €<br>
|
|||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<button onclick="saveDomain()">Save</button>
|
<button id="domainSaveBtn" onclick="saveDomain()">Save</button>
|
||||||
<button onclick="closeDomainModal()">Cancel</button>
|
<button onclick="closeDomainModal()">Cancel</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -302,6 +303,7 @@ Domains jährlich: <span id="costDomain">0</span> €<br>
|
|||||||
<div id="subdomainModal" class="modal">
|
<div id="subdomainModal" class="modal">
|
||||||
|
|
||||||
<h3>Subdomain erstellen</h3>
|
<h3>Subdomain erstellen</h3>
|
||||||
|
<div id="subdomainModalMeta" class="modal-meta"></div>
|
||||||
|
|
||||||
<input type="hidden" id="sub_domain_id">
|
<input type="hidden" id="sub_domain_id">
|
||||||
<input type="hidden" id="sub_id">
|
<input type="hidden" id="sub_id">
|
||||||
@@ -314,7 +316,7 @@ Domains jährlich: <span id="costDomain">0</span> €<br>
|
|||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<button onclick="saveSubdomain()">Save</button>
|
<button id="subdomainSaveBtn" onclick="saveSubdomain()">Save</button>
|
||||||
<button onclick="closeSubModal()">Cancel</button>
|
<button onclick="closeSubModal()">Cancel</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const API = "/resman/api"
|
const API = "/resman/api"
|
||||||
|
|
||||||
async function api(url, options = {}) {
|
async function api(url, options = {}, config = {}) {
|
||||||
|
const showToast = config.showError !== false
|
||||||
const res = await fetch(url, options)
|
const res = await fetch(url, options)
|
||||||
|
|
||||||
let data
|
let data
|
||||||
@@ -14,10 +15,35 @@ async function api(url, options = {}) {
|
|||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const msg = data.error || "Unbekannter Fehler"
|
const msg = data.error || "Unbekannter Fehler"
|
||||||
|
|
||||||
showError(msg)
|
if (showToast) {
|
||||||
|
showError(msg)
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(msg)
|
const error = new Error(msg)
|
||||||
|
error.status = res.status
|
||||||
|
error.data = data
|
||||||
|
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.runAction = async function(action, onSuccess) {
|
||||||
|
try {
|
||||||
|
await action()
|
||||||
|
|
||||||
|
if (onSuccess) {
|
||||||
|
await onSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
if (error && error.silent) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ async function getDNS(domain){
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
|
|
||||||
const res = await api(API + "/dns/" + domain)
|
const res = await api(API + "/dns/" + domain, {}, { showError: false })
|
||||||
const ips = res.ips || []
|
const ips = res.ips || []
|
||||||
|
|
||||||
dnsCache[domain] = {
|
dnsCache[domain] = {
|
||||||
@@ -47,6 +47,7 @@ window.loadDomains = async function(){
|
|||||||
|
|
||||||
const domains = await api(API + "/domains")
|
const domains = await api(API + "/domains")
|
||||||
const subs = await api(API + "/subdomains")
|
const subs = await api(API + "/subdomains")
|
||||||
|
window.domainList = domains
|
||||||
|
|
||||||
const table = document.getElementById("domains")
|
const table = document.getElementById("domains")
|
||||||
table.innerHTML = ""
|
table.innerHTML = ""
|
||||||
@@ -208,28 +209,34 @@ window.saveDomain = async function(){
|
|||||||
notes: domain_notes.value
|
notes: domain_notes.value
|
||||||
}
|
}
|
||||||
|
|
||||||
if(id){
|
await runAction(
|
||||||
|
async () => {
|
||||||
|
if(id){
|
||||||
|
|
||||||
await api(API+"/domains/"+id,{
|
await api(API+"/domains/"+id,{
|
||||||
method:"PUT",
|
method:"PUT",
|
||||||
headers:{'Content-Type':'application/json'},
|
headers:{'Content-Type':'application/json'},
|
||||||
body:JSON.stringify(data)
|
body:JSON.stringify(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
await api(API+"/domains",{
|
await api(API+"/domains",{
|
||||||
method:"POST",
|
method:"POST",
|
||||||
headers:{'Content-Type':'application/json'},
|
headers:{'Content-Type':'application/json'},
|
||||||
body:JSON.stringify(data)
|
body:JSON.stringify(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
closeDomainModal()
|
async () => {
|
||||||
loadDomains()
|
closeDomainModal()
|
||||||
loadMapping()
|
await loadDomains()
|
||||||
loadCosts()
|
await loadMapping()
|
||||||
|
loadCosts()
|
||||||
|
loadInfrastructure()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,29 +245,36 @@ window.deleteDomain = async function(id){
|
|||||||
|
|
||||||
if(!confirm("Domain löschen?")) return
|
if(!confirm("Domain löschen?")) return
|
||||||
|
|
||||||
await api(API + "/domains/" + id, {
|
await runAction(
|
||||||
method: "DELETE"
|
async () => {
|
||||||
})
|
await api(API + "/domains/" + id, {
|
||||||
|
method: "DELETE"
|
||||||
loadDomains()
|
})
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
await loadDomains()
|
||||||
|
await loadMapping()
|
||||||
|
loadCosts()
|
||||||
|
loadInfrastructure()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.moveDomain = async function(id, direction){
|
window.moveDomain = async function(id, direction){
|
||||||
|
await runAction(
|
||||||
try{
|
async () => {
|
||||||
|
await api(API + "/domains/" + id + "/move", {
|
||||||
await api(API + "/domains/" + id + "/move", {
|
method: "POST",
|
||||||
method: "POST",
|
headers: {'Content-Type':'application/json'},
|
||||||
headers: {'Content-Type':'application/json'},
|
body: JSON.stringify({ direction })
|
||||||
body: JSON.stringify({ direction })
|
})
|
||||||
})
|
},
|
||||||
|
async () => {
|
||||||
loadDomains()
|
await loadDomains()
|
||||||
loadMapping()
|
await loadMapping()
|
||||||
|
loadInfrastructure()
|
||||||
}catch(e){
|
}
|
||||||
console.log(e)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -277,26 +291,33 @@ window.saveSubdomain = async function(){
|
|||||||
|
|
||||||
const data = { domain_id, subdomain, ip_address }
|
const data = { domain_id, subdomain, ip_address }
|
||||||
|
|
||||||
if(id){
|
await runAction(
|
||||||
|
async () => {
|
||||||
|
if(id){
|
||||||
|
|
||||||
await api(API+"/subdomains/"+id,{
|
await api(API+"/subdomains/"+id,{
|
||||||
method:"PUT",
|
method:"PUT",
|
||||||
headers:{'Content-Type':'application/json'},
|
headers:{'Content-Type':'application/json'},
|
||||||
body:JSON.stringify(data)
|
body:JSON.stringify(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
await api(API+"/subdomains",{
|
await api(API+"/subdomains",{
|
||||||
method:"POST",
|
method:"POST",
|
||||||
headers:{'Content-Type':'application/json'},
|
headers:{'Content-Type':'application/json'},
|
||||||
body:JSON.stringify(data)
|
body:JSON.stringify(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
closeSubModal()
|
async () => {
|
||||||
loadDomains()
|
closeSubModal()
|
||||||
|
await loadDomains()
|
||||||
|
await loadMapping()
|
||||||
|
loadInfrastructure()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,11 +326,18 @@ window.deleteSub = async function(id){
|
|||||||
|
|
||||||
if(!confirm("Subdomain löschen?")) return
|
if(!confirm("Subdomain löschen?")) return
|
||||||
|
|
||||||
await api(API + "/subdomains/" + id, {
|
await runAction(
|
||||||
method: "DELETE"
|
async () => {
|
||||||
})
|
await api(API + "/subdomains/" + id, {
|
||||||
|
method: "DELETE"
|
||||||
loadDomains()
|
})
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
await loadDomains()
|
||||||
|
await loadMapping()
|
||||||
|
loadInfrastructure()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ document.getElementById("serverDetailModal").style.display="none"
|
|||||||
window.openDomainCreate = function(){
|
window.openDomainCreate = function(){
|
||||||
|
|
||||||
document.getElementById("domainModalTitle").innerText = "Create Domain"
|
document.getElementById("domainModalTitle").innerText = "Create Domain"
|
||||||
|
document.getElementById("domainModalMeta").innerText = "Neue Domain anlegen"
|
||||||
|
|
||||||
document.getElementById("domain_id").value = ""
|
document.getElementById("domain_id").value = ""
|
||||||
document.getElementById("domain_name").value = ""
|
document.getElementById("domain_name").value = ""
|
||||||
@@ -133,8 +134,10 @@ window.openDomainCreate = function(){
|
|||||||
document.getElementById("domain_ip").value = ""
|
document.getElementById("domain_ip").value = ""
|
||||||
document.getElementById("domain_cost").value = ""
|
document.getElementById("domain_cost").value = ""
|
||||||
document.getElementById("domain_notes").value = ""
|
document.getElementById("domain_notes").value = ""
|
||||||
|
document.getElementById("domainSaveBtn").innerText = "Create"
|
||||||
|
|
||||||
openModal("domainModal")
|
openModal("domainModal")
|
||||||
|
document.getElementById("domain_name").focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,6 +145,7 @@ window.openDomainCreate = function(){
|
|||||||
window.openDomainEdit = function(d){
|
window.openDomainEdit = function(d){
|
||||||
|
|
||||||
document.getElementById("domainModalTitle").innerText="Edit Domain"
|
document.getElementById("domainModalTitle").innerText="Edit Domain"
|
||||||
|
document.getElementById("domainModalMeta").innerText=d.domain_name || ""
|
||||||
|
|
||||||
document.getElementById("domain_id").value=d.id
|
document.getElementById("domain_id").value=d.id
|
||||||
|
|
||||||
@@ -150,8 +154,10 @@ document.getElementById("domain_provider").value=d.provider || ""
|
|||||||
document.getElementById("domain_ip").value=d.ip_address || ""
|
document.getElementById("domain_ip").value=d.ip_address || ""
|
||||||
document.getElementById("domain_cost").value=d.yearly_cost || ""
|
document.getElementById("domain_cost").value=d.yearly_cost || ""
|
||||||
document.getElementById("domain_notes").value=d.notes || ""
|
document.getElementById("domain_notes").value=d.notes || ""
|
||||||
|
document.getElementById("domainSaveBtn").innerText = "Update"
|
||||||
|
|
||||||
document.getElementById("domainModal").style.display="block"
|
document.getElementById("domainModal").style.display="block"
|
||||||
|
document.getElementById("domain_name").focus()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,17 +172,23 @@ window.closeDomainModal = function(){
|
|||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
window.openSubCreate = function(domainId){
|
window.openSubCreate = function(domainId){
|
||||||
|
const domains = window.domainList || []
|
||||||
|
const domain = domains.find(d => d.id == domainId)
|
||||||
|
const domainName = domain?.domain_name || "Unbekannte Domain"
|
||||||
|
|
||||||
document.getElementById("sub_id").value = "" // RESET !!
|
document.getElementById("sub_id").value = "" // RESET !!
|
||||||
|
|
||||||
document.getElementById("sub_domain_id").value = domainId
|
document.getElementById("sub_domain_id").value = domainId
|
||||||
document.getElementById("sub_name").value = ""
|
document.getElementById("sub_name").value = ""
|
||||||
document.getElementById("sub_ip").value = ""
|
document.getElementById("sub_ip").value = domain?.ip_address || ""
|
||||||
|
|
||||||
document.querySelector("#subdomainModal h3").innerText = "Subdomain erstellen"
|
document.querySelector("#subdomainModal h3").innerText = "Subdomain erstellen"
|
||||||
|
document.getElementById("subdomainModalMeta").innerText = "Fuer " + domainName
|
||||||
|
document.getElementById("subdomainSaveBtn").innerText = "Create"
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("subdomainModal").style.display="block"
|
document.getElementById("subdomainModal").style.display="block"
|
||||||
|
document.getElementById("sub_name").focus()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +199,7 @@ window.closeSubModal = function(){
|
|||||||
|
|
||||||
|
|
||||||
window.openSubEdit = function(s){
|
window.openSubEdit = function(s){
|
||||||
|
const fullName = s.subdomain + "." + s.domain_name
|
||||||
|
|
||||||
document.getElementById("sub_id").value = s.id
|
document.getElementById("sub_id").value = s.id
|
||||||
document.getElementById("sub_domain_id").value = s.domain_id
|
document.getElementById("sub_domain_id").value = s.domain_id
|
||||||
@@ -195,8 +208,11 @@ document.getElementById("sub_name").value = s.subdomain
|
|||||||
document.getElementById("sub_ip").value = s.ip_address
|
document.getElementById("sub_ip").value = s.ip_address
|
||||||
|
|
||||||
document.querySelector("#subdomainModal h3").innerText = "Subdomain bearbeiten"
|
document.querySelector("#subdomainModal h3").innerText = "Subdomain bearbeiten"
|
||||||
|
document.getElementById("subdomainModalMeta").innerText = fullName
|
||||||
|
document.getElementById("subdomainSaveBtn").innerText = "Update"
|
||||||
|
|
||||||
document.getElementById("subdomainModal").style.display="block"
|
document.getElementById("subdomainModal").style.display="block"
|
||||||
|
document.getElementById("sub_name").focus()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,20 +111,35 @@ window.saveResource = async function(){
|
|||||||
bemerkung:bemerkung.value
|
bemerkung:bemerkung.value
|
||||||
}
|
}
|
||||||
|
|
||||||
if(id){
|
await runAction(
|
||||||
await api(API+"/resources/"+id,{method:"PUT",headers:{'Content-Type':'application/json'},body:JSON.stringify(data)})
|
async () => {
|
||||||
}else{
|
if(id){
|
||||||
await api(API+"/resources",{method:"POST",headers:{'Content-Type':'application/json'},body:JSON.stringify(data)})
|
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)})
|
||||||
closeModal()
|
}
|
||||||
loadResources()
|
},
|
||||||
|
async () => {
|
||||||
|
closeModal()
|
||||||
|
await loadResources()
|
||||||
|
loadInfrastructure()
|
||||||
|
loadCosts()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.deleteResource = async function(id){
|
window.deleteResource = async function(id){
|
||||||
if(!confirm("delete resource?")) return
|
if(!confirm("delete resource?")) return
|
||||||
await api(API+"/resources/"+id,{method:"DELETE"})
|
await runAction(
|
||||||
loadResources()
|
async () => {
|
||||||
|
await api(API+"/resources/"+id,{method:"DELETE"})
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
await loadResources()
|
||||||
|
loadInfrastructure()
|
||||||
|
loadCosts()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.checkServerStatus = async function(resource){
|
window.checkServerStatus = async function(resource){
|
||||||
@@ -187,46 +202,51 @@ window.saveIP = async function(){
|
|||||||
const type = document.getElementById("new_type").value
|
const type = document.getElementById("new_type").value
|
||||||
const comment = document.getElementById("new_comment").value
|
const comment = document.getElementById("new_comment").value
|
||||||
|
|
||||||
if(id){
|
await runAction(
|
||||||
// 🔥 UPDATE
|
async () => {
|
||||||
await api(API + "/ips/" + id, {
|
if(id){
|
||||||
method: "PUT",
|
await api(API + "/ips/" + id, {
|
||||||
headers: {'Content-Type':'application/json'},
|
method: "PUT",
|
||||||
body: JSON.stringify({ip, type, comment})
|
headers: {'Content-Type':'application/json'},
|
||||||
})
|
body: JSON.stringify({ip, type, comment})
|
||||||
|
})
|
||||||
|
|
||||||
delete ipField.dataset.editId
|
delete ipField.dataset.editId
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// 🔥 CREATE
|
try{
|
||||||
|
const result = await api(API + "/ipcheck/" + ip, {}, { showError: false })
|
||||||
|
|
||||||
try{
|
if(result.length){
|
||||||
const result = await api(API + "/ipcheck/" + ip)
|
if(!confirm("IP existiert bereits. Trotzdem speichern?")){
|
||||||
|
const error = new Error("IP save cancelled")
|
||||||
if(result.length){
|
error.silent = true
|
||||||
if(!confirm("IP existiert bereits. Trotzdem speichern?")){
|
throw error
|
||||||
return
|
}
|
||||||
|
}
|
||||||
|
}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})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}catch(e){
|
},
|
||||||
console.log("Save IP Fehler:", e)
|
async () => {
|
||||||
|
ipField.value = ""
|
||||||
|
document.getElementById("new_type").value = ""
|
||||||
|
document.getElementById("new_comment").value = ""
|
||||||
|
|
||||||
|
await loadIPs(resourceId)
|
||||||
|
await loadResources()
|
||||||
|
loadInfrastructure()
|
||||||
|
cancelIPEdit()
|
||||||
}
|
}
|
||||||
|
)
|
||||||
await api(API + "/resources/" + resourceId + "/ips", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {'Content-Type':'application/json'},
|
|
||||||
body: JSON.stringify({ip, type, comment})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Felder reset
|
|
||||||
ipField.value = ""
|
|
||||||
document.getElementById("new_type").value = ""
|
|
||||||
document.getElementById("new_comment").value = ""
|
|
||||||
|
|
||||||
loadIPs(resourceId)
|
|
||||||
loadResources()
|
|
||||||
cancelIPEdit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -234,12 +254,18 @@ window.deleteIP = async function(id, resourceId){
|
|||||||
|
|
||||||
if(!confirm("IP löschen?")) return
|
if(!confirm("IP löschen?")) return
|
||||||
|
|
||||||
await api(API + "/ips/" + id, {
|
await runAction(
|
||||||
method: "DELETE"
|
async () => {
|
||||||
})
|
await api(API + "/ips/" + id, {
|
||||||
|
method: "DELETE"
|
||||||
loadIPs(resourceId) // Modal neu laden
|
})
|
||||||
loadResources() // Tabelle aktualisieren
|
},
|
||||||
|
async () => {
|
||||||
|
await loadIPs(resourceId)
|
||||||
|
await loadResources()
|
||||||
|
loadInfrastructure()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,19 +343,18 @@ window.cancelIPEdit = function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.moveResource = async function(id, direction){
|
window.moveResource = async function(id, direction){
|
||||||
|
await runAction(
|
||||||
try {
|
async () => {
|
||||||
|
await api(API + "/resources/" + id + "/move", {
|
||||||
await api(API + "/resources/" + id + "/move", {
|
method: "POST",
|
||||||
method: "POST",
|
headers: { 'Content-Type': 'application/json' },
|
||||||
headers: { 'Content-Type': 'application/json' },
|
body: JSON.stringify({ direction })
|
||||||
body: JSON.stringify({ direction })
|
})
|
||||||
})
|
},
|
||||||
|
async () => {
|
||||||
loadResources()
|
await loadResources()
|
||||||
|
loadInfrastructure()
|
||||||
} catch (e) {
|
loadCosts()
|
||||||
console.log(e)
|
}
|
||||||
}
|
)
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user