@@ -368,8 +368,8 @@ function handleNodes($method, $id, $db) {
|
|||||||
case 'POST':
|
case 'POST':
|
||||||
$data = json_decode(file_get_contents('php://input'), true);
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
INSERT INTO network_nodes (label, ip_address, node_type, status, group_name, pos_x, pos_y)
|
INSERT INTO network_nodes (label, ip_address, node_type, status, group_name, pos_x, pos_y, notes)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
");
|
");
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
$data['label'],
|
$data['label'],
|
||||||
@@ -378,7 +378,8 @@ function handleNodes($method, $id, $db) {
|
|||||||
$data['status'] ?? 'unknown',
|
$data['status'] ?? 'unknown',
|
||||||
$data['group_name'] ?? 'default',
|
$data['group_name'] ?? 'default',
|
||||||
$data['pos_x'] ?? 0,
|
$data['pos_x'] ?? 0,
|
||||||
$data['pos_y'] ?? 0
|
$data['pos_y'] ?? 0,
|
||||||
|
$data['notes'] ?? ''
|
||||||
]);
|
]);
|
||||||
echo json_encode(['id' => $db->lastInsertId()]);
|
echo json_encode(['id' => $db->lastInsertId()]);
|
||||||
break;
|
break;
|
||||||
@@ -387,7 +388,7 @@ function handleNodes($method, $id, $db) {
|
|||||||
$data = json_decode(file_get_contents('php://input'), true);
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
$fields = [];
|
$fields = [];
|
||||||
$params = [];
|
$params = [];
|
||||||
foreach (['label','ip_address','node_type','status','group_name','pos_x','pos_y'] as $f) {
|
foreach (['label','ip_address','node_type','status','group_name','pos_x','pos_y','notes'] as $f) {
|
||||||
if (isset($data[$f])) {
|
if (isset($data[$f])) {
|
||||||
$fields[] = "$f = ?";
|
$fields[] = "$f = ?";
|
||||||
$params[] = $data[$f];
|
$params[] = $data[$f];
|
||||||
|
|||||||
@@ -38,4 +38,6 @@ function migrate($db) {
|
|||||||
role ENUM('admin','user') DEFAULT 'user',
|
role ENUM('admin','user') DEFAULT 'user',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
)");
|
)");
|
||||||
|
// Add notes column if missing
|
||||||
|
try { $db->exec("ALTER TABLE network_nodes ADD COLUMN notes TEXT DEFAULT ''"); } catch (Exception $e) {}
|
||||||
}
|
}
|
||||||
@@ -393,6 +393,7 @@ function selectNode(id, add) {
|
|||||||
'<div><span class="text-secondary">Type:</span> ' + n.node_type + '</div>' +
|
'<div><span class="text-secondary">Type:</span> ' + n.node_type + '</div>' +
|
||||||
'<div><span class="text-secondary">Status:</span> ' + n.status + '</div>' +
|
'<div><span class="text-secondary">Status:</span> ' + n.status + '</div>' +
|
||||||
'<div><span class="text-secondary">Group:</span> ' + n.group_name + '</div>' +
|
'<div><span class="text-secondary">Group:</span> ' + n.group_name + '</div>' +
|
||||||
|
(n.notes ? '<div class="mt-1 p-1 rounded" style="background:#0d1117;font-size:.75rem;color:#94a3b8;"><i class="fas fa-sticky-note me-1"></i>' + esc(n.notes) + '</div>' : '') +
|
||||||
(selectedNodeIds.length > 1 ? '<small class="text-secondary">+' + (selectedNodeIds.length - 1) + ' more selected</small>' : '') +
|
(selectedNodeIds.length > 1 ? '<small class="text-secondary">+' + (selectedNodeIds.length - 1) + ' more selected</small>' : '') +
|
||||||
'<div class="mt-2 d-flex gap-1">' +
|
'<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-primary btn-sm" onclick="editSelectedNode(' + n.id + ')"><i class="fas fa-pen me-1"></i>Edit</button>' +
|
||||||
@@ -495,6 +496,7 @@ async function saveNode() {
|
|||||||
node_type: document.getElementById('nodeType').value,
|
node_type: document.getElementById('nodeType').value,
|
||||||
status: document.getElementById('nodeStatus').value,
|
status: document.getElementById('nodeStatus').value,
|
||||||
group_name: document.getElementById('nodeGroup').value || 'default',
|
group_name: document.getElementById('nodeGroup').value || 'default',
|
||||||
|
notes: document.getElementById('nodeNotes').value,
|
||||||
pos_x: Math.random() * canvas.width * 0.6 + canvas.width * 0.2 - panX,
|
pos_x: Math.random() * canvas.width * 0.6 + canvas.width * 0.2 - panX,
|
||||||
pos_y: Math.random() * canvas.height * 0.6 + canvas.height * 0.2 - panY
|
pos_y: Math.random() * canvas.height * 0.6 + canvas.height * 0.2 - panY
|
||||||
};
|
};
|
||||||
@@ -502,7 +504,8 @@ async function saveNode() {
|
|||||||
if (editingNodeId) {
|
if (editingNodeId) {
|
||||||
await apiFetch('nodes/' + editingNodeId, { method: 'PUT', body: JSON.stringify({
|
await apiFetch('nodes/' + editingNodeId, { method: 'PUT', body: JSON.stringify({
|
||||||
label: data.label, ip_address: data.ip_address,
|
label: data.label, ip_address: data.ip_address,
|
||||||
node_type: data.node_type, status: data.status, group_name: data.group_name
|
node_type: data.node_type, status: data.status,
|
||||||
|
group_name: data.group_name, notes: data.notes
|
||||||
})});
|
})});
|
||||||
editingNodeId = null;
|
editingNodeId = null;
|
||||||
} else {
|
} else {
|
||||||
@@ -524,6 +527,7 @@ function editSelectedNode(id) {
|
|||||||
document.getElementById('nodeType').value = n.node_type;
|
document.getElementById('nodeType').value = n.node_type;
|
||||||
document.getElementById('nodeStatus').value = n.status;
|
document.getElementById('nodeStatus').value = n.status;
|
||||||
document.getElementById('nodeGroup').value = n.group_name;
|
document.getElementById('nodeGroup').value = n.group_name;
|
||||||
|
document.getElementById('nodeNotes').value = n.notes || '';
|
||||||
document.getElementById('nodeModalLabel').textContent = 'Edit Network Node';
|
document.getElementById('nodeModalLabel').textContent = 'Edit Network Node';
|
||||||
document.getElementById('saveNode').innerHTML = '<i class="fas fa-save me-1"></i> Update Node';
|
document.getElementById('saveNode').innerHTML = '<i class="fas fa-save me-1"></i> Update Node';
|
||||||
new bootstrap.Modal(document.getElementById('nodeModal')).show();
|
new bootstrap.Modal(document.getElementById('nodeModal')).show();
|
||||||
|
|||||||
@@ -240,6 +240,10 @@
|
|||||||
<label class="form-label small">Group</label>
|
<label class="form-label small">Group</label>
|
||||||
<input type="text" class="form-control form-control-sm" id="nodeGroup" placeholder="e.g. DMZ, Internal, Cloud">
|
<input type="text" class="form-control form-control-sm" id="nodeGroup" placeholder="e.g. DMZ, Internal, Cloud">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label small">Notes</label>
|
||||||
|
<textarea class="form-control form-control-sm" id="nodeNotes" rows="2" placeholder="Tags, descriptions, vulnerabilities..."></textarea>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer border-secondary">
|
<div class="modal-footer border-secondary">
|
||||||
|
|||||||
Reference in New Issue
Block a user