adding editing to network map
Deploy / deploy (push) Successful in 38s

This commit is contained in:
2026-05-07 19:35:34 +02:00
parent 1f24977f26
commit 1cf8d9f664
2 changed files with 71 additions and 11 deletions
+69 -9
View File
@@ -26,6 +26,8 @@ let selectRect = null;
let nextShapeZ = 0;
let copyBuffer = null;
let editingNodeId = null;
let editingShapeId = null;
document.addEventListener('DOMContentLoaded', () => {
canvas = document.getElementById('networkCanvas');
@@ -275,7 +277,10 @@ function renderShapeList() {
<span style="display:inline-block;width:12px;height:12px;border-radius:2px;background:${s.border_color};margin-right:.4rem;"></span>
<strong class="small">${esc(s.label) || (s.shape_type === 'rectangle' ? 'Box' : 'Ellipse')}</strong>
</div>
<small class="text-secondary">${s.shape_type}</small>
<div>
<small class="text-secondary me-2">${s.shape_type}</small>
<button class="btn btn-sm btn-outline-primary py-0 px-1" onclick="event.stopPropagation();editSelectedShape(${s.id})" title="Edit"><i class="fas fa-pen" style="font-size:.7rem;"></i></button>
</div>
</div>
</div>
`).join('');
@@ -301,7 +306,10 @@ function selectNode(id, add = false) {
<div><span class="text-secondary">Status:</span> ${n.status}</div>
<div><span class="text-secondary">Group:</span> ${n.group_name}</div>
${selectedNodeIds.length > 1 ? `<small class="text-secondary">+${selectedNodeIds.length - 1} more selected</small>` : ''}
<button class="btn btn-outline-danger btn-sm mt-2" onclick="deleteSelectedNodes()"><i class="fas fa-trash me-1"></i>Delete</button>
<div class="mt-2 d-flex gap-1">
<button class="btn btn-outline-primary btn-sm" onclick="editSelectedNode(${n.id})"><i class="fas fa-pen me-1"></i>Edit</button>
<button class="btn btn-outline-danger btn-sm" onclick="deleteSelectedNodes()"><i class="fas fa-trash me-1"></i>Delete</button>
</div>
</div>
`;
}
@@ -417,12 +425,55 @@ async function saveNode() {
pos_y: Math.random() * canvas.height * 0.6 + canvas.height * 0.2 - panY
};
if (!data.label) return alert('Label required');
await apiFetch('nodes', { method: 'POST', body: JSON.stringify(data) });
if (editingNodeId) {
const updates = {
label: data.label,
ip_address: data.ip_address,
node_type: data.node_type,
status: data.status,
group_name: data.group_name
};
await apiFetch(`nodes/${editingNodeId}`, { method: 'PUT', body: JSON.stringify(updates) });
editingNodeId = null;
} else {
await apiFetch('nodes', { method: 'POST', body: JSON.stringify(data) });
}
bootstrap.Modal.getInstance(document.getElementById('nodeModal')).hide();
document.getElementById('nodeForm').reset();
document.getElementById('nodeModalLabel').textContent = 'Add Network Node';
document.getElementById('saveNode').innerHTML = '<i class="fas fa-save me-1"></i> Add Node';
loadNetworkData();
}
function editSelectedNode(id) {
const n = nodes.find(x => x.id == id);
if (!n) return;
editingNodeId = id;
document.getElementById('nodeLabel').value = n.label;
document.getElementById('nodeIp').value = n.ip_address || '';
document.getElementById('nodeType').value = n.node_type;
document.getElementById('nodeStatus').value = n.status;
document.getElementById('nodeGroup').value = n.group_name;
document.getElementById('nodeModalLabel').textContent = 'Edit Network Node';
document.getElementById('saveNode').innerHTML = '<i class="fas fa-save me-1"></i> Update Node';
new bootstrap.Modal(document.getElementById('nodeModal')).show();
}
function editSelectedShape(id) {
const s = shapes.find(x => x.id == id);
if (!s) return;
editingShapeId = id;
document.getElementById('shapeLabel').value = s.label;
document.getElementById('shapeType').value = s.shape_type;
document.getElementById('shapeColor').value = s.color;
document.getElementById('shapeBorderColor').value = s.border_color;
document.getElementById('shapeOpacity').value = s.opacity;
document.getElementById('opacityVal').textContent = s.opacity;
document.getElementById('shapeModalLabel').textContent = 'Edit Shape';
document.getElementById('saveShape').innerHTML = '<i class="fas fa-save me-1"></i> Update Shape';
new bootstrap.Modal(document.getElementById('shapeModal')).show();
}
async function saveLink() {
const data = {
source_id: document.getElementById('linkSource').value,
@@ -441,18 +492,27 @@ async function saveShape() {
const data = {
label: document.getElementById('shapeLabel').value,
shape_type: document.getElementById('shapeType').value,
pos_x: canvas.width / 2 - 100 - panX,
pos_y: canvas.height / 2 - 75 - panY,
width: 200,
height: 150,
color: document.getElementById('shapeColor').value,
border_color: document.getElementById('shapeBorderColor').value,
opacity: parseFloat(document.getElementById('shapeOpacity').value),
z_index: nextShapeZ++
};
await apiFetch('shapes', { method: 'POST', body: JSON.stringify(data) });
if (editingShapeId) {
const s = shapes.find(x => x.id == editingShapeId);
data.pos_x = s.pos_x; data.pos_y = s.pos_y; data.width = s.width; data.height = s.height; data.z_index = s.z_index;
await apiFetch(`shapes/${editingShapeId}`, { method: 'PUT', body: JSON.stringify(data) });
editingShapeId = null;
} else {
data.pos_x = canvas.width / 2 - 100 - panX;
data.pos_y = canvas.height / 2 - 75 - panY;
data.width = 200;
data.height = 150;
data.z_index = nextShapeZ++;
await apiFetch('shapes', { method: 'POST', body: JSON.stringify(data) });
}
bootstrap.Modal.getInstance(document.getElementById('shapeModal')).hide();
document.getElementById('shapeForm').reset();
document.getElementById('shapeModalLabel').textContent = 'Add Shape';
document.getElementById('saveShape').innerHTML = '<i class="fas fa-save me-1"></i> Add Shape';
loadNetworkData();
}
+2 -2
View File
@@ -193,7 +193,7 @@
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header border-secondary">
<h5 class="modal-title"><i class="fas fa-desktop text-primary me-1"></i> Add Network Node</h5>
<h5 class="modal-title"><i class="fas fa-desktop text-primary me-1"></i> <span id="nodeModalLabel">Add Network Node</span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
@@ -249,7 +249,7 @@
<div class="modal-dialog modal-sm">
<div class="modal-content bg-dark">
<div class="modal-header border-secondary">
<h5 class="modal-title"><i class="fas fa-vector-square text-info me-1"></i> Add Shape</h5>
<h5 class="modal-title"><i class="fas fa-vector-square text-info me-1"></i> <span id="shapeModalLabel">Add Shape</span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">