- Fix invisible device while dragging from front to rear: the block
being dragged stayed structurally inside its own source <svg>, so it
rendered underneath the other panel once it visually overlapped it.
Replaced the in-SVG transform with a free-floating HTML ghost fixed
to <body> that tracks the pointer, unaffected by either SVG's own
stacking - the original block just dims in place during the drag, as
before.
- Fix rear elevation showing nothing for a device type with no
rear_image: only full-depth devices (which have a genuinely
different back) are restricted to their own rear image now; a
shallow device (e.g. a PDU) falls back to its front image on the
rear view, since that's usually the only picture that exists and is
still recognisable either way.
- Shorten the drag-hint badge text; the German translation of the
previous, longer wording didn't fit well next to the other controls
above the elevation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Front and rear panels already share one coordinate system (same
UNIT_HEIGHT, RACK_X, ...), just placed side by side on screen, so the
existing delta-based drag math is equally valid for a drop on the
other panel - only needed to detect which face the pointer ended up
over (elementFromPoint at drop time) and include it as `face` in the
submitted move; the reorder endpoint already supported changing it.
Also fixed a bug this surfaced: without pointer-events: none on the
dragged block during the drag, elementFromPoint() at drop time always
hit the dragged block itself (it's what's rendered under the cursor),
never the panel actually underneath - cross-face drops would never
have been detected. Pointer capture keeps delivering move/up events to
the block regardless of its own pointer-events value, so this is safe.
Added overflow: visible on the elevation SVGs so a device being
dragged toward the other panel doesn't just vanish at its own SVG's
edge mid-drag.
Updated the German translation for the changed drag-hint string.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Investigated how MrBlake/mrb-netbox-topology-views does its PNG export:
it renders its topology natively onto a canvas (vis-network draws
there directly) and just calls canvas.toDataURL() - no SVG round-trip
at all. Applied the same principle here.
Previous approach loaded the standalone SVG export via <img src="blob:...">
and rasterized that onto a canvas - fragile, because the whole export
failed if that SVG document wasn't strictly valid XML (as our leaked
{# #} comment bug demonstrated) or if a single device type image
reference inside it couldn't be resolved.
New approach: a dedicated export/data/ endpoint returns the elevation's
plain pixel geometry as JSON (positions, sizes, colors, labels, image
URLs - the same numbers the SVG is built from), and export.js draws
that directly onto a <canvas> with native 2D primitives (fillRect,
strokeRect, fillText/strokeText, drawImage). Device type images are
fetched individually as same-origin blobs before drawing; one image
failing to load only drops that picture; the rest of the export still
succeeds. Added a combined front+rear PNG option.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Fix template comments rendering as literal text: Django's {# #} tag
regex (tag_re in django/template/base.py) has no re.DOTALL, so a
comment spanning multiple lines is never recognized as a tag at all
and leaks into the rendered output verbatim - exactly what showed up
under "Elevation". Collapsed all three offending comments to single
lines. This was also almost certainly the real cause of the "PNG
could not be generated" report: two of the leaked comments sat
inside the shared SVG partial, corrupting the exported SVG enough
that the browser's image decoder rejected it (my own onerror handler
then showed a misleading CORS-sounding message - the actual bug was
malformed markup, not cross-origin images).
- Add a German translation (locale/de/), built from every _() and
{% trans %}/{% blocktrans %} string in the plugin (269 entries,
cross-checked against the source for completeness). English needs no
catalog of its own since it's the literal source text; both were
already listed in NetBox's own language selector.
- Add CHANGELOG.md and bump the version to 0.2.0, covering this and
every unreleased change so far; will keep bumping per change from
here on.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Introduces a NetBox 4.6 plugin for planning rack layouts (RackConcept,
ConceptDevice) without creating real dcim.Rack/dcim.Device objects, so
blueprints never appear in rack/device lists, utilization reports, or
IPAM.
Features:
- Copy paths: real rack -> concept, concept -> concept (clone), and
concept -> one or more real racks (deploy, with name patterning and
dry-run support)
- Manual concept creation via a dedicated "Rack Concepts" nav menu
- Tenant and tenant group assignment on concepts and planned devices
- Partial-width device placement (1/1-1/4) with slot-based collision
detection, matching netbox_utilities' partial-width feature
- Custom drag-and-drop elevation (netbox-reorder-rack operates on real
Device querysets, which concepts don't have) with server-side
validation of every move
- Full REST API, filtering, CSV import, bulk edit, search integration
- Optional, config-driven interop with netbox_utilities (partial-width
field mapping) and netbox-reorder-rack, degrading gracefully when
either plugin is absent
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>