Commit Graph
11 Commits
Author SHA1 Message Date
MrBlakeandClaude Sonnet 5 1793bf13e2 v0.2.3: visible cross-panel drag ghost, front-image fallback, shorter hint
- 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>
2026-09-16 14:01:42 +02:00
MrBlakeandClaude Sonnet 5 41141ec318 v0.2.2: support dragging a device between front and rear elevations
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>
2026-09-16 13:50:57 +02:00
MrBlakeandClaude Sonnet 5 67d999e234 v0.2.1: rework PNG export to draw directly on canvas, like netbox-topology-views
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>
2026-09-16 12:53:42 +02:00
MrBlakeandClaude Sonnet 5 3420d84803 v0.2.0: fix leaked multi-line {# #} comments, add German translation
- 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>
2026-09-16 12:45:01 +02:00
MrBlakeandClaude Sonnet 5 2c991e37ae Add SVG/PNG/draw.io export for rack concepts, center the add-device hint
- Extract the elevation's <svg> body into inc/elevation_svg_content.html,
  shared by the on-page elevation and a new standalone export template
  so they never drift apart.
- Add "Export" dropdown above the elevation: Front/Rear as standalone
  SVG (self-contained inline styles, no dependency on the page's CSS,
  absolute device-type image URLs so the file still works once saved
  elsewhere), Front/Rear as PNG (rasterized entirely client-side via
  <canvas> from that same SVG - no new server-side image dependency),
  and the whole concept as a draw.io (.drawio / mxGraph XML) diagram
  with both faces side by side, reusing the identical block geometry.
- Center the "+ Add device" hint on empty units instead of
  right-aligning it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 12:34:26 +02:00
MrBlakeandClaude Sonnet 5 b289bc5aeb Mirror device cabling 1:1 (per-type tabs) and copy cables on rack import
- Split the device detail page's single "Components" table into the
  same seven tabs a real dcim.Device has, in the same order: Console
  Ports, Console Server Ports, Power Ports, Power Outlets, Interfaces,
  Front Ports, Rear Ports. Each tab is its own ObjectChildrenView
  filtered by component_type (one ConceptComponent model backs all of
  them, so this only needed the view/URL layer, not a schema change),
  hidden when empty, exactly like core NetBox. Replace the ad hoc "Add
  component" button with the same "Add Components" dropdown real
  device pages use, one entry per type, each landing back on its own
  tab.
- When copying a real rack into a concept (or merging two real racks
  into one), automatically sync every copied device's components and
  recreate, as ConceptCables, every real cable whose both ends land on
  one of those devices - reading the same CableTermination data dcim
  itself uses, so the copy comes out cabled internally the same as the
  source. Cables reaching outside the copied rack(s), or multi-
  termination trunk cables, are skipped and reported as a count in the
  success message - the other end isn't part of the concept, so it
  can't be represented. copy_rack_to_concept() and
  merge_racks_to_concept() now return an extra cable_summary value;
  updated all their callers (views and API).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 10:34:26 +02:00
MrBlakeandClaude Sonnet 5 63538c2efe Fix rear-face image-only labels, click-to-add units, cable concept devices
- Fix "images only" leaving plain labels visible on faces where a
  device has no image for that side (e.g. no rear_image set): the
  view selector now hides every plain label outright in that mode,
  not just the ones an image happens to sit on top of.
- Remove the "Add planned device" button from the elevation card.
  Empty units are now click targets themselves - clicking one opens
  the add-device form pre-filled with that position and face, exactly
  like a real rack's elevation. Occupancy is computed per unit per
  face from the existing device blocks.
- Add cabling for concept devices: ConceptComponent (interfaces,
  front/rear ports, power ports/outlets, console ports) and
  ConceptCable (a connection between two components, restricted to
  devices in the same concept). components.sync_components()
  populates a device's components from its device type's templates,
  including the front/rear port pass-through mapping copied from
  DeviceType.port_mappings - so a device with front/rear port
  templates (a patch panel being the common case) behaves exactly
  like a real one, without hardcoding anything role-specific.
  Placeholder devices without a device type get components added by
  hand. Full CRUD views, tables, filtersets, API endpoints and a
  "Connect" action wired in from the device detail page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 10:18:50 +02:00
MrBlakeandClaude Sonnet 5 e4817ea83b Add images/labels toggle, clean up label styling, merge real racks
- Replace the device-image label background bar and text-shadow with
  NetBox's own technique: a black-stroke pass behind a white-fill pass
  of the same text, giving crisp readable labels over any image
  without a dark box behind them.
- Add an "Images and labels / Images only / Labels only" selector
  above the elevation, mirroring the equivalent control on real NetBox
  rack elevations. The plain label is always in the markup; the
  selector only toggles the image and its over-image label, exactly
  like core NetBox does it. Choice persists per browser via
  localStorage and works without edit permissions.
- Add a "Merge into concept" button to the real dcim Rack list: select
  two racks via the existing bulk-select checkboxes and it forwards
  them to the concept-merge page, pre-filled. New
  deploy.merge_racks_to_concept() combines two real racks' devices
  directly into one new, stacked blueprint without an intermediate
  per-rack copy step.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 09:50:23 +02:00
MrBlakeandClaude Sonnet 5 777ded3900 Fix elevation overlap, add device images, rack merge, and size override
- Fix elevation rendering bug: device blocks were drawn MARGIN px
  further right than the rack frame/unit slots, causing them to
  overlap and extend past the right border. All three now share one
  RACK_X origin.
- Show the device type's front/rear image inside each elevation block
  (clipped to the block, translucent label bar on top for legibility)
  when one is set on the device type; falls back to a plain colour
  block with text otherwise.
- Add "Merge" action to combine two concepts into one taller one (e.g.
  two half-height racks stacked into a full-height rack): the top
  concept's devices are shifted up by the bottom concept's height,
  neither source is modified. Available from the plugin menu, from a
  concept's detail page, and via POST /concepts/merge/.
- Copying a real rack into a concept can now target a different width,
  height and/or starting unit than the source rack; devices that no
  longer fit at the chosen size are skipped and reported as warnings
  instead of aborting the copy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 09:35:18 +02:00
MrBlakeandClaude Sonnet 5 7b9b85776b Document pip install/update via git repo in README
Adds instructions for installing and upgrading the plugin directly via
pip from git.mrblake.cc, including pinning a ref, wiring it into
local_requirements.txt for upgrade.sh, and the force-reinstall caveat
needed to pick up updates from an unversioned git URL.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 09:02:15 +02:00
MrBlakeandClaude Sonnet 5 17cf94ac0d Add netbox_rack_concept plugin: rack blueprint planning
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>
2026-09-16 09:00:26 +02:00