Render rack elevations using HTML5 SVG #1851

Closed
opened 2025-12-29 17:19:46 +01:00 by adam · 17 comments
Owner

Originally created by @jeremystretch on GitHub (Jul 18, 2018).

Originally assigned to: @hellerve on GitHub.

Issue type

[x] Feature request
[ ] Bug report
[ ] Documentation
[ ] Housekeeping

Environment

  • Python version: 3.5.2
  • NetBox version: 2.3.6

Description

Currently, rack elevations are rendered in HTML as multi-layered lists of divs, which is exactly as terrible as it sounds. While this approach has been reasonably sufficient, an elevation's fixed size and limited screen space has led to several limitations:

  • #160 - Rack elevations are not printer-friendly
  • #1911 - Difficult to show child devices within a parent
  • #1998 - Elevations do not include status information

The idea was raised in #1529 to adopt HTML5's canvas feature and render racks as free-form drawings. While this will take a substantial amount of effort on the backend, it should result in a much cleaner and more flexible illustration of rack elevations.

Further research into the feasibility of this feature is needed, but I wanted to get it on the board for reference.

Originally created by @jeremystretch on GitHub (Jul 18, 2018). Originally assigned to: @hellerve on GitHub. ### Issue type [x] Feature request <!-- An enhancement of existing functionality --> [ ] Bug report <!-- Unexpected or erroneous behavior --> [ ] Documentation <!-- A modification to the documentation --> [ ] Housekeeping <!-- Changes pertaining to the codebase itself --> ### Environment * Python version: 3.5.2 * NetBox version: 2.3.6 ### Description Currently, rack elevations are rendered in HTML as multi-layered lists of divs, which is exactly as terrible as it sounds. While this approach has been reasonably sufficient, an elevation's fixed size and limited screen space has led to several limitations: * #160 - Rack elevations are not printer-friendly * #1911 - Difficult to show child devices within a parent * #1998 - Elevations do not include status information The idea was raised in #1529 to adopt HTML5's canvas feature and render racks as free-form drawings. While this will take a substantial amount of effort on the backend, it should result in a _much_ cleaner and more flexible illustration of rack elevations. Further research into the feasibility of this feature is needed, but I wanted to get it on the board for reference.
adam added the status: accepted label 2025-12-29 17:19:46 +01:00
adam closed this issue 2025-12-29 17:19:46 +01:00
Author
Owner

@jeremystretch commented on GitHub (Jul 19, 2018):

fabric.js looks pretty promising.

@jeremystretch commented on GitHub (Jul 19, 2018): [fabric.js](http://fabricjs.com/) looks pretty promising.
Author
Owner

@jeremystretch commented on GitHub (Jul 24, 2018):

Upon experimentation, HTML5's SVG rendering feature seems more practical than using the canvas.

@jeremystretch commented on GitHub (Jul 24, 2018): Upon experimentation, HTML5's [SVG rendering feature](https://www.w3schools.com/html/html5_svg.asp) seems more practical than using the canvas.
Author
Owner

@andre-lx commented on GitHub (Nov 16, 2018):

Look at the svg.js.

Uses pure svg instead of canvas (fabric.js) and seems ideal so that in future other features can be added, like childs inside parents on rack and cable visualization.

@andre-lx commented on GitHub (Nov 16, 2018): Look at the svg.js. Uses pure svg instead of canvas (fabric.js) and seems ideal so that in future other features can be added, like childs inside parents on rack and cable visualization.
Author
Owner

@tb-killa commented on GitHub (Jan 21, 2019):

Hi @jeremystretch i build a simple Sample via "svg.js".
https://jsfiddle.net/tb_killa/1wu5stgj/

It´s not perfect but it shows you that this could work.

@tb-killa commented on GitHub (Jan 21, 2019): Hi @jeremystretch i build a simple Sample via "svg.js". https://jsfiddle.net/tb_killa/1wu5stgj/ It´s not perfect but it shows you that this could work.
Author
Owner

@candlerb commented on GitHub (May 31, 2019):

We have had good success doing Netbox visualizations using the d3 js library - although here is an argument against

@candlerb commented on GitHub (May 31, 2019): We have had good success doing Netbox visualizations using the [d3 js](https://github.com/d3/d3) library - although here is an [argument against](https://medium.com/@PepsRyuu/why-i-no-longer-use-d3-js-b8288f306c9a)
Author
Owner

@hellerve commented on GitHub (Nov 15, 2019):

Have we decided on a framework yet? I’d volunteer to work on this unless anyone has started to work already!

@hellerve commented on GitHub (Nov 15, 2019): Have we decided on a framework yet? I’d volunteer to work on this unless anyone has started to work already!
Author
Owner

@jeremystretch commented on GitHub (Nov 15, 2019):

I believe there's a strong desire for the ability to return SVG files directly from the API, without requiring any UI-centric processing (e.g. something like fabric.js). This would enable the diagrams to be rendered on-demand and embedded in other applications. (I'm not sure about the details concerning how we'd deliver non-JSON content yet.)

@jeremystretch commented on GitHub (Nov 15, 2019): I believe there's a strong desire for the ability to return SVG files directly from the API, without requiring any UI-centric processing (e.g. something like fabric.js). This would enable the diagrams to be rendered on-demand and embedded in other applications. (I'm not sure about the details concerning how we'd deliver non-JSON content yet.)
Author
Owner

@hellerve commented on GitHub (Nov 15, 2019):

Alright, I can look into that. I don’t have a ton of experience building SVGs, especially on the backend, but I’ll let you know what I can come up with!

@hellerve commented on GitHub (Nov 15, 2019): Alright, I can look into that. I don’t have a ton of experience building SVGs, especially on the backend, but I’ll let you know what I can come up with!
Author
Owner

@hellerve commented on GitHub (Nov 18, 2019):

I’m in the process of building a PoC for this. It’s fairly dirty for now as I’m learning how to work with the svwgrite python package, but it’s getting somewhere and I expect this to reach feature parity soon-ish.

For now I’m inlining the styles into the elements. Alternatively we could link to the styles inside the SVG, but that seems like an annoyance (it would mean that we depend on the server/delivering the stylesheet from within the SVG). We could also provide a global stylesheet to the SVG, but that too would mean storing it somewhere (this could even be made configurable, but going down that route seems overkill to me). What do you think?

@hellerve commented on GitHub (Nov 18, 2019): I’m in the process of building a PoC for this. It’s fairly dirty for now as I’m learning how to work with the [svwgrite python package](https://svgwrite.readthedocs.io/), but it’s getting somewhere and I expect this to reach feature parity soon-ish. For now I’m inlining the styles into the elements. Alternatively we could link to the styles inside the SVG, but that seems like an annoyance (it would mean that we depend on the server/delivering the stylesheet from within the SVG). We could also provide a global stylesheet to the SVG, but that too would mean storing it somewhere (this could even be made configurable, but going down that route seems overkill to me). What do you think?
Author
Owner

@tb-killa commented on GitHub (Nov 20, 2019):

Nice work @hellerve 👍
Would you add Screenshot to show the result please ?
As i could see you only generate front_view actually right ?

@tb-killa commented on GitHub (Nov 20, 2019): Nice work @hellerve :+1: Would you add Screenshot to show the result please ? As i could see you only generate front_view actually right ?
Author
Owner

@hellerve commented on GitHub (Nov 20, 2019):

Yeah, it’s totally not done and currently still WIP. I really only wanted to see how to make this work. I’ll add a screenshot once I’ve sorted out a bunch of SVG things (most notably, centering text and changing the font)! I probably won’t be able to work on this again until the weekend though.

@hellerve commented on GitHub (Nov 20, 2019): Yeah, it’s totally not done and currently still WIP. I really only wanted to see how to make this work. I’ll add a screenshot once I’ve sorted out a bunch of SVG things (most notably, centering text and changing the font)! I probably won’t be able to work on this again until the weekend though.
Author
Owner

@jeremystretch commented on GitHub (Nov 20, 2019):

@hellerve Just keep in mind it's best to share work early and often, to avoid going too far down the wrong path.

@jeremystretch commented on GitHub (Nov 20, 2019): @hellerve Just keep in mind it's best to share work early and often, to avoid going too far down the wrong path.
Author
Owner

@hellerve commented on GitHub (Nov 20, 2019):

Totally, but I’d like to make it work at least a little bit before bothering y’all :)

@hellerve commented on GitHub (Nov 20, 2019): Totally, but I’d like to make it work at least a little bit before bothering y’all :)
Author
Owner

@jeremystretch commented on GitHub (Nov 20, 2019):

It's not a bother. If you'd like to share your overall strategy here or on the mailing list that would be great.

Also, it's taking longer than anticipated to get the v2.7 beta out. I was hoping to get it done by the end of the month but I'm not sure that's realistic anymore. Depending on how much work the SVG stuff will take, we may have to push it to a future release.

@jeremystretch commented on GitHub (Nov 20, 2019): It's not a bother. If you'd like to share your overall strategy here or on the mailing list that would be great. Also, it's taking longer than anticipated to get the v2.7 beta out. I was hoping to get it done by the end of the month but I'm not sure that's realistic anymore. Depending on how much work the SVG stuff will take, we may have to push it to a future release.
Author
Owner

@hellerve commented on GitHub (Nov 20, 2019):

Alright, I can explain my prototype a bit and explain a few of the as-of-yet open questions:

As I mentioned above the package that I’m currently using is svgwrite. It is only used in one API endpoint in the prototype: /api/dcim/rack-elevations/<pk>. This API endpoint renders the rack elevation—in the current code only the front, and that should be the default, but you would be able to choose the side by a query parameter—as an SVG and returns the response with the appropriate content type. It thus stands out from the other JSON-based API calls, but I think it makes sense to have it there.

A lot of the code for actually rendering the stack is technically similar to what we used to do in the template: go through the units one-by-one, render it in the appropriate color, put a link in, etc. It’s not that complicated, and I think that means we’re on the right track.

As of yet, there are a few things that are missing or are as of yet unimplemented:

  1. Being able to choose front and back. That shouldn’t be a problem and, because my coding hands are starting to itch, I’ll try to fix that right after finishing this comment. It’s not going to be more than a few lines I don’t think.
  2. A few specific SVG styling issues.
    2.1. I haven’t found out how to actually center text in a text box using the library yet, but I’m sure if I dig enough I’ll find it.
    2.2. I don’t know how to change the font, and the default font (Times New Roman) doesn’t exactly look appealing and, in the context of the app and its unified typography, definitely looks out of place.
    2.3. The logic to change the font color based on the background color also needs to be replicated.
  3. Reservations. I haven’t started on them yet.
  4. Making it a little more modular. While the S in SVG stands for scalable, I’m still using magic numbers everywhere to align everything size-wise, and the color strings are currently inline. I don’t necessarily think that they need to be customizable or anything, but offloading a bunch of the color work to a stylesheet (probably an inline one) might make a lot of sense. I’ll have to investigate that too. EDIT: I settled for an inline stylesheet in the source code for now. I don’t like that approach very much, and if anyone has a better idea, let me know!
  5. Clean it up. The main loop is weirdly structured, and I’m hoping that by pulling it apart and moving a bunch of the styling code somewhere else it will fall into place.
  6. EDIT: the hover text for the links is also yet to be created!
  7. Hover tooltips with device information.

Generally, I think most of why this is taking me a few hours to implement is my ignorance when it comes to both SVG and this particular library, and having to dig through readthedocs a whole lot to locate the functionality that I’m looking for. It’s a bit of a painful process, but we’re getting there.

I don’t see any major roadblockers coming up if the task stays “just reimplement the racks using SVG for now”. I expect that we can do some tweaking then, and that the code generally looks less daunting afterwards (it being purely Python already makes it more appealing to me personally).

As for a timeline, I can’t commit to anything yet, but if I’m lucky I’ll be motivated enough tonight to push one or two of the easier things into place right away. The rest will have to wait for the weekend and possibly longer (though I’ll keep you updated on my progress).

@hellerve commented on GitHub (Nov 20, 2019): Alright, I can explain my prototype a bit and explain a few of the as-of-yet open questions: As I mentioned above the package that I’m currently using is `svgwrite`. It is only used in one API endpoint in the prototype: `/api/dcim/rack-elevations/<pk>`. This API endpoint renders the rack elevation—in the current code only the front, and that should be the default, but you would be able to choose the side by a query parameter—as an SVG and returns the response with the appropriate content type. It thus stands out from the other JSON-based API calls, but I think it makes sense to have it there. A lot of the code for actually rendering the stack is technically similar to what we used to do in the template: go through the units one-by-one, render it in the appropriate color, put a link in, etc. It’s not that complicated, and I think that means we’re on the right track. As of yet, there are a few things that are missing or are as of yet unimplemented: 1. ~Being able to choose front and back. That shouldn’t be a problem and, because my coding hands are starting to itch, I’ll try to fix that right after finishing this comment. It’s not going to be more than a few lines I don’t think.~ 2. ~A few specific SVG styling issues.~ 2.1. ~I haven’t found out how to actually center text in a text box using the library yet, but I’m sure if I dig enough I’ll find it.~ 2.2. ~I don’t know how to change the font, and the default font (Times New Roman) doesn’t exactly look appealing and, in the context of the app and its unified typography, definitely looks out of place.~ 2.3. ~The logic to change the font color based on the background color also needs to be replicated.~ 3. ~Reservations. I haven’t started on them yet.~ 4. Making it a little more modular. While the S in SVG stands for scalable, I’m still using magic numbers everywhere to align everything size-wise, and the color strings are currently inline. I don’t necessarily think that they need to be customizable or anything, but offloading a bunch of the color work to a stylesheet (probably an inline one) might make a lot of sense. I’ll have to investigate that too. EDIT: I settled for an inline stylesheet in the source code for now. I don’t like that approach very much, and if anyone has a better idea, let me know! 5. Clean it up. The main loop is weirdly structured, and I’m hoping that by pulling it apart and moving a bunch of the styling code somewhere else it will fall into place. 6. ~EDIT: the hover text for the links is also yet to be created!~ 7. Hover tooltips with device information. Generally, I think most of why this is taking me a few hours to implement is my ignorance when it comes to both SVG and this particular library, and having to dig through readthedocs a whole lot to locate the functionality that I’m looking for. It’s a bit of a painful process, but we’re getting there. I don’t see any major roadblockers coming up if the task stays “just reimplement the racks using SVG for now”. I expect that we can do some tweaking then, and that the code generally looks less daunting afterwards (it being purely Python already makes it more appealing to me personally). As for a timeline, I can’t commit to anything yet, but if I’m lucky I’ll be motivated enough tonight to push one or two of the easier things into place right away. The rest will have to wait for the weekend and possibly longer (though I’ll keep you updated on my progress).
Author
Owner

@hellerve commented on GitHub (Nov 21, 2019):

Here’s a screenshot of what requesting an example Rack (the request goes to/api/dcim/rack-elevations/1/?face=rear, in this case) currently looks like:

As you can see, a bunch of the base rendering logic is there, including fonts and coloring and such. What you cannot see is that the hover links to add device also work. A few of the generic styling things have already been offloaded to a stylesheet.

Reservations are still missing, but they shouldn’t be a big deal. A thing that is kind of annoying that I haven’t thought about much yet—and it makes me want to despair a little when I do—are the tooltips that are added per device on hover. They are replicable for sure, but I feel like that wouldn’t make it very SVG-y anymore and move it more into the world of an embeddable HTML page. Did you have any thoughts about this going in, @jeremystretch?

I’ve also thought about devices rendering themselves—as in, you ask the device to return a SVG data structure through a function like as_svg or something along those lines—, which sounds kind of cute but also like it would taint the model even more (and the device model class is huge already).

Also, if you trust strangers on the internet, here’s the actual SVG packed into a ZIP (because GitHub allows you to upload ZIPs but not SVGs, which is a funny threat model):

elevations.zip

This file should allow you to see the whole thing including hovering.

@hellerve commented on GitHub (Nov 21, 2019): Here’s a screenshot of what requesting an example Rack (the request goes to`/api/dcim/rack-elevations/1/?face=rear`, in this case) currently looks like: <img src="https://user-images.githubusercontent.com/7725188/69331253-bca5f380-0c54-11ea-9f3c-de784e1dbc68.png" height="400"> As you can see, a bunch of the base rendering logic is there, including fonts and coloring and such. What you cannot see is that the hover links to `add device` also work. A few of the generic styling things have already been offloaded to a stylesheet. Reservations are still missing, but they shouldn’t be a big deal. A thing that _is_ kind of annoying that I haven’t thought about much yet—and it makes me want to despair a little when I do—are the tooltips that are added per device on hover. They are replicable for sure, but I feel like that wouldn’t make it very SVG-y anymore and move it more into the world of an embeddable HTML page. Did you have any thoughts about this going in, @jeremystretch? I’ve also thought about devices rendering themselves—as in, you ask the device to return a SVG data structure through a function like `as_svg` or something along those lines—, which sounds kind of cute but also like it would taint the model even more (and the device model class is _huge_ already). Also, if you trust strangers on the internet, here’s the actual SVG packed into a ZIP (because GitHub allows you to upload ZIPs but not SVGs, which is a funny threat model): [elevations.zip](https://github.com/netbox-community/netbox/files/3874301/elevations.zip) This file should allow you to see the whole thing including hovering.
Author
Owner

@hellerve commented on GitHub (Nov 21, 2019):

I opened a draft PR for this, so you can play around with it if you wish to!

@hellerve commented on GitHub (Nov 21, 2019): I opened a draft PR for this, so you can play around with it if you wish to!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#1851