mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-11 21:10:29 +01:00
Render rack elevations using HTML5 SVG #1851
Closed
opened 2025-12-29 17:19:46 +01:00 by adam
·
17 comments
No Branch/Tag Specified
main
update-changelog-comments-docs
feature-removal-issue-type
20911-dropdown
20239-plugin-menu-classes-mutable-state
21097-graphql-id-lookups
feature
fix_module_substitution
20923-dcim-templates
20044-elevation-stuck-lightmode
feature-ip-prefix-link
v4.5-beta1-release
20068-import-moduletype-attrs
20766-fix-german-translation-code-literals
20378-del-script
7604-filter-modifiers-v3
circuit-swap
12318-case-insensitive-uniqueness
20637-improve-device-q-filter
20660-script-load
19724-graphql
20614-update-ruff
14884-script
02496-max-page
19720-macaddress-interface-generic-relation
19408-circuit-terminations-export-templates
20203-openapi-check
fix-19669-api-image-download
7604-filter-modifiers
19275-fixes-interface-bulk-edit
fix-17794-get_field_value_return_list
11507-show-aggregate-and-rir-on-api
9583-add_column_specific_search_field_to_tables
v4.5.0
v4.4.10
v4.4.9
v4.5.0-beta1
v4.4.8
v4.4.7
v4.4.6
v4.4.5
v4.4.4
v4.4.3
v4.4.2
v4.4.1
v4.4.0
v4.3.7
v4.4.0-beta1
v4.3.6
v4.3.5
v4.3.4
v4.3.3
v4.3.2
v4.3.1
v4.3.0
v4.2.9
v4.3.0-beta2
v4.2.8
v4.3.0-beta1
v4.2.7
v4.2.6
v4.2.5
v4.2.4
v4.2.3
v4.2.2
v4.2.1
v4.2.0
v4.1.11
v4.1.10
v4.1.9
v4.1.8
v4.2-beta1
v4.1.7
v4.1.6
v4.1.5
v4.1.4
v4.1.3
v4.1.2
v4.1.1
v4.1.0
v4.0.11
v4.0.10
v4.0.9
v4.1-beta1
v4.0.8
v4.0.7
v4.0.6
v4.0.5
v4.0.3
v4.0.2
v4.0.1
v4.0.0
v3.7.8
v3.7.7
v4.0-beta2
v3.7.6
v3.7.5
v4.0-beta1
v3.7.4
v3.7.3
v3.7.2
v3.7.1
v3.7.0
v3.6.9
v3.6.8
v3.6.7
v3.7-beta1
v3.6.6
v3.6.5
v3.6.4
v3.6.3
v3.6.2
v3.6.1
v3.6.0
v3.5.9
v3.6-beta2
v3.5.8
v3.6-beta1
v3.5.7
v3.5.6
v3.5.5
v3.5.4
v3.5.3
v3.5.2
v3.5.1
v3.5.0
v3.4.10
v3.4.9
v3.5-beta2
v3.4.8
v3.5-beta1
v3.4.7
v3.4.6
v3.4.5
v3.4.4
v3.4.3
v3.4.2
v3.4.1
v3.4.0
v3.3.10
v3.3.9
v3.4-beta1
v3.3.8
v3.3.7
v3.3.6
v3.3.5
v3.3.4
v3.3.3
v3.3.2
v3.3.1
v3.3.0
v3.2.9
v3.2.8
v3.3-beta2
v3.2.7
v3.3-beta1
v3.2.6
v3.2.5
v3.2.4
v3.2.3
v3.2.2
v3.2.1
v3.2.0
v3.1.11
v3.1.10
v3.2-beta2
v3.1.9
v3.2-beta1
v3.1.8
v3.1.7
v3.1.6
v3.1.5
v3.1.4
v3.1.3
v3.1.2
v3.1.1
v3.1.0
v3.0.12
v3.0.11
v3.0.10
v3.1-beta1
v3.0.9
v3.0.8
v3.0.7
v3.0.6
v3.0.5
v3.0.4
v3.0.3
v3.0.2
v3.0.1
v3.0.0
v2.11.12
v3.0-beta2
v2.11.11
v2.11.10
v3.0-beta1
v2.11.9
v2.11.8
v2.11.7
v2.11.6
v2.11.5
v2.11.4
v2.11.3
v2.11.2
v2.11.1
v2.11.0
v2.10.10
v2.10.9
v2.11-beta1
v2.10.8
v2.10.7
v2.10.6
v2.10.5
v2.10.4
v2.10.3
v2.10.2
v2.10.1
v2.10.0
v2.9.11
v2.10-beta2
v2.9.10
v2.10-beta1
v2.9.9
v2.9.8
v2.9.7
v2.9.6
v2.9.5
v2.9.4
v2.9.3
v2.9.2
v2.9.1
v2.9.0
v2.9-beta2
v2.8.9
v2.9-beta1
v2.8.8
v2.8.7
v2.8.6
v2.8.5
v2.8.4
v2.8.3
v2.8.2
v2.8.1
v2.8.0
v2.7.12
v2.7.11
v2.7.10
v2.7.9
v2.7.8
v2.7.7
v2.7.6
v2.7.5
v2.7.4
v2.7.3
v2.7.2
v2.7.1
v2.7.0
v2.6.12
v2.6.11
v2.6.10
v2.6.9
v2.7-beta1
Solcon-2020-01-06
v2.6.8
v2.6.7
v2.6.6
v2.6.5
v2.6.4
v2.6.3
v2.6.2
v2.6.1
v2.6.0
v2.5.13
v2.5.12
v2.6-beta1
v2.5.11
v2.5.10
v2.5.9
v2.5.8
v2.5.7
v2.5.6
v2.5.5
v2.5.4
v2.5.3
v2.5.2
v2.5.1
v2.5.0
v2.4.9
v2.5-beta2
v2.4.8
v2.5-beta1
v2.4.7
v2.4.6
v2.4.5
v2.4.4
v2.4.3
v2.4.2
v2.4.1
v2.4.0
v2.3.7
v2.4-beta1
v2.3.6
v2.3.5
v2.3.4
v2.3.3
v2.3.2
v2.3.1
v2.3.0
v2.2.10
v2.3-beta2
v2.2.9
v2.3-beta1
v2.2.8
v2.2.7
v2.2.6
v2.2.5
v2.2.4
v2.2.3
v2.2.2
v2.2.1
v2.2.0
v2.1.6
v2.2-beta2
v2.1.5
v2.2-beta1
v2.1.4
v2.1.3
v2.1.2
v2.1.1
v2.1.0
v2.0.10
v2.1-beta1
v2.0.9
v2.0.8
v2.0.7
v2.0.6
v2.0.5
v2.0.4
v2.0.3
v2.0.2
v2.0.1
v2.0.0
v2.0-beta3
v1.9.6
v1.9.5
v2.0-beta2
v1.9.4-r1
v1.9.3
v2.0-beta1
v1.9.2
v1.9.1
v1.9.0-r1
v1.8.4
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.7.3
v1.7.2-r1
v1.7.1
v1.7.0
v1.6.3
v1.6.2-r1
v1.6.1-r1
1.6.1
v1.6.0
v1.5.2
v1.5.1
v1.5.0
v1.4.2
v1.4.1
v1.4.0
v1.3.2
v1.3.1
v1.3.0
v1.2.2
v1.2.1
v1.2.0
v1.1.0
v1.0.7-r1
v1.0.7
v1.0.6
v1.0.5
v1.0.4
v1.0.3-r1
v1.0.3
1.0.0
Labels
Clear labels
beta
breaking change
complexity: high
complexity: low
complexity: medium
needs milestone
netbox
pending closure
plugin candidate
pull-request
severity: high
severity: low
severity: medium
status: accepted
status: backlog
status: blocked
status: duplicate
status: needs owner
status: needs triage
status: revisions needed
status: under review
topic: GraphQL
topic: Internationalization
topic: OpenAPI
topic: UI/UX
topic: cabling
topic: event rules
topic: htmx navigation
topic: industrialization
topic: migrations
topic: plugins
topic: scripts
topic: templating
topic: testing
type: bug
type: deprecation
type: documentation
type: feature
type: housekeeping
type: translation
Mirrored from GitHub Pull Request
No Label
status: accepted
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: starred/netbox#1851
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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
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:
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.
@jeremystretch commented on GitHub (Jul 19, 2018):
fabric.js looks pretty promising.
@jeremystretch commented on GitHub (Jul 24, 2018):
Upon experimentation, HTML5's SVG rendering feature seems more practical than using the canvas.
@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.
@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.
@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
@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!
@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.)
@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 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?
@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 ?
@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.
@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.
@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 :)
@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.
@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:
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.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.Reservations. I haven’t started on them yet.EDIT: the hover text for the links is also yet to be created!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 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 devicealso 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_svgor 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):
I opened a draft PR for this, so you can play around with it if you wish to!