Skip to content

Commit 5c2ff07

Browse files
peterbaumertPeter Baumert
andauthored
feat(svg): add partial connection indicator for SVG renderer (#62)
Introduces a third connection state for the SVG rendering path: - Full connection (green) — both cable ends resolve to a device - Partial connection (yellow + dot) — cable attached but far-end has no device - Unconnected/disabled — unchanged grey/red A yellow warning dot is injected into the top-right corner of each partially connected port via JS, remaining visible even when cable colour mode overrides the fill colour. Closes #61 Co-authored-by: Peter Baumert <peter.baumert@outlook.com>
1 parent 9dc34bf commit 5c2ff07

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

netbox_device_view/static/netbox_device_view/css/device_view_svg.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
.dv-port.bg-success .dv-port-rect { fill: #198754; }
7777
.dv-port.bg-secondary .dv-port-rect { fill: #6c757d; }
7878
.dv-port.bg-danger .dv-port-rect { fill: #dc3545; }
79+
/* Partial connection: cable attached but far-end has no device */
80+
.dv-port.bg-warning .dv-port-rect { fill: #ffc107; }
7981

8082
/* Cable colour override — applied inline via JS (style attribute on .dv-port) */
8183
/* No rule needed; the JS sets fill on .dv-port-rect directly */
@@ -85,6 +87,15 @@
8587
fill: url(#dv-nocolor-pattern);
8688
}
8789

90+
/* Partial connection dot overlay — small warning circle in the top-right corner.
91+
Always rendered on top of the port rect, visible even in cable colour mode. */
92+
.dv-partial-dot {
93+
fill: #ffc107;
94+
stroke: #333;
95+
stroke-width: 0.5;
96+
pointer-events: none;
97+
}
98+
8899
/* ── Structural elements ───────────────────────────────────────────────────── */
89100

90101
.dv-spacer {

netbox_device_view/templates/netbox_device_view/deviceview.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
name: "{{ int.name|escapejs }}",
119119
enabled: {% if int.enabled or int.is_port %}true{% else %}false{% endif %},
120120
connected: {% if int.connected_endpoints|length > 0 or int.is_port and int.link_peers|length > 0 %}true{% else %}false{% endif %},
121+
partiallyConnected: {% if int.link_peers|length > 0 and int.connected_endpoints|length == 0 %}true{% else %}false{% endif %},
121122
cableColor: "{% if cable_colors == 'on' and int.cable.color != '' %}{{ int.cable.color }}{% endif %}",
122123
cableNoColor: {% if cable_colors == "on" and int.cable.color == "" or cable_colors == "on" and int.cable == None %}true{% else %}false{% endif %},
123124
connectedEndpoints: [{% for ce in int.connected_endpoints %}"{{ ce.device }} | {{ ce.name }}"{% if not forloop.last %},{% endif %}{% endfor %}],
@@ -139,12 +140,25 @@
139140
if (rect) rect.setAttribute("fill", "#" + p.cableColor);
140141
} else if (p.connected) {
141142
g.classList.add("bg-success");
143+
} else if (p.partiallyConnected) {
144+
g.classList.add("bg-warning");
142145
} else if (p.enabled) {
143146
g.classList.add("bg-secondary");
144147
} else {
145148
g.classList.add("bg-danger");
146149
}
147150

151+
// Always show a small warning dot for partially connected ports,
152+
// even when cable color mode overrides the fill colour.
153+
if (p.partiallyConnected && rect) {
154+
var dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
155+
dot.setAttribute("class", "dv-partial-dot");
156+
dot.setAttribute("cx", parseFloat(rect.getAttribute("x")) + parseFloat(rect.getAttribute("width")) - 3);
157+
dot.setAttribute("cy", parseFloat(rect.getAttribute("y")) + 3);
158+
dot.setAttribute("r", "2.5");
159+
g.appendChild(dot);
160+
}
161+
148162
g.setAttribute("role", "link");
149163
g.style.cursor = "pointer";
150164
g.addEventListener("click", function () { window.location.href = p.url; });

netbox_device_view/templates/netbox_device_view/ports.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ <h2 class="card-header">Deviceview {{ object.name }}</h2>
115115
name: "{{ int.name|escapejs }}",
116116
enabled: {% if int.enabled or int.is_port %}true{% else %}false{% endif %},
117117
connected: {% if int.connected_endpoints|length > 0 or int.is_port and int.link_peers|length > 0 %}true{% else %}false{% endif %},
118+
partiallyConnected: {% if int.link_peers|length > 0 and int.connected_endpoints|length == 0 %}true{% else %}false{% endif %},
118119
cableColor: "{% if cable_colors == 'on' and int.cable.color != '' %}{{ int.cable.color }}{% endif %}",
119120
cableNoColor: {% if cable_colors == "on" and int.cable.color == "" or cable_colors == "on" and int.cable == None %}true{% else %}false{% endif %},
120121
connectedEndpoints: [{% for ce in int.connected_endpoints %}"{{ ce.device }} | {{ ce.name }}"{% if not forloop.last %},{% endif %}{% endfor %}],
@@ -135,11 +136,25 @@ <h2 class="card-header">Deviceview {{ object.name }}</h2>
135136
if (rect) rect.setAttribute("fill", "#" + p.cableColor);
136137
} else if (p.connected) {
137138
g.classList.add("bg-success");
139+
} else if (p.partiallyConnected) {
140+
g.classList.add("bg-warning");
138141
} else if (p.enabled) {
139142
g.classList.add("bg-secondary");
140143
} else {
141144
g.classList.add("bg-danger");
142145
}
146+
147+
// Always show a small warning dot for partially connected ports,
148+
// even when cable color mode overrides the fill colour.
149+
if (p.partiallyConnected && rect) {
150+
var dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
151+
dot.setAttribute("class", "dv-partial-dot");
152+
dot.setAttribute("cx", parseFloat(rect.getAttribute("x")) + parseFloat(rect.getAttribute("width")) - 3);
153+
dot.setAttribute("cy", parseFloat(rect.getAttribute("y")) + 3);
154+
dot.setAttribute("r", "2.5");
155+
g.appendChild(dot);
156+
}
157+
143158
g.setAttribute("role", "link");
144159
g.style.cursor = "pointer";
145160
g.addEventListener("click", function () { window.location.href = p.url; });

0 commit comments

Comments
 (0)