Network Mapper - edmozley/freeitsm GitHub Wiki

Network Mapper

Folder: network-mapper/ Colour: Cyan gradient

Visual architecture diagrams that stay bound to the CMDB. Every node on the canvas references a real cmdb_objects row β€” not a free-floating label β€” so the diagram can't drift from reality. Rename an object in CMDB and the diagram updates. Mark it as planned and it renders with a dashed amber border. Decommission it and the diagram says so.

network_1

The killer feature is Add related objects β€” pick any placed node, click one button, and the modal lists every CMDB neighbour (outgoing relationships, incoming relationships, property references). Tick the ones you want, hit Add, and they land in a ring around the source with connectors auto-drawn β€” guided graph exploration rather than blank-canvas overwhelm.

Diagrams Landing Page (network-mapper/)

Grid of cards showing each diagram's title, version pill (showing the chain length when a diagram has more than one version), description, node + connector counts, author, and last-updated date. Filter by title. + New diagram modal collects title, optional description, and an initial version label (defaults to v1). Click a card to open the editor.

Editor (network-mapper/diagram.php?id=X)

Three-pane layout: class palette on the left, canvas in the middle, detail panel on the right (slides in when a node is selected). Editor toolbar across the top with status / view / branding / export controls.

Class Palette

Lists every active CMDB class with its icon and object count. Drag a class tile onto the canvas to place a node of that class.

Placing Nodes

  1. Drag a class tile onto the canvas
  2. Drop opens an object picker scoped to that class β€” type-ahead filter, arrow keys + Enter to pick
  3. Picker auto-filters out objects already on this diagram (no double-placing)
  4. Node lands at the drop coordinates, snapped to the 20px grid, with the object's name as the label

Click to select, drag to move, Delete to remove. Click an empty area of the canvas to deselect.

A few behaviours worth knowing:

  • The picker preloads the class's full object list; the type-ahead filter re-queries server-side with a 200ms debounce
  • A drag only marks the diagram dirty if the node actually moved, so a click-without-drag selects but doesn't dirty
  • Every successful save re-fetches the diagram so temp ids (negative numbers used for unsaved nodes) resolve into real auto-increment ids β€” vital before any connector references a node. The current selection is preserved across the reload by matching on cmdb_object_id rather than node id
  • Deleting a node cascades down any incident connectors so save_diagram.php doesn't reject the payload
  • Read-only versions accept selection but reject drop / drag / delete (the backend would refuse anyway)

Connectors

Hover or select a node β€” four small cyan edge handles appear at the icon's top/right/bottom/left. Mousedown on a handle, drag to another node, mouseup to create the connector. A dashed cyan line tracks the cursor during the drag.

  • Direction matters: arrows point from source to target in the draw order
  • Double-click a connector β†’ inline cyan-bordered input opens at the midpoint for the label (Enter saves, Esc cancels)
  • Select a connector β†’ cyan stroke + arrowhead; Delete removes it
  • Wider invisible hit-area path underneath each connector makes them easy to click
  • Endpoint geometry snaps to the side of each icon's bounding box that faces the other node, so lines stay sensible after dragging either end around
  • Label editing also saves on blur; an emptied label clears it
  • Self-loops and duplicate connectors (same direction between the same pair) are silently refused
  • Connectors between two brand-new (unsaved) nodes save in a single round-trip β€” both nodes' negative tempIds and the connector's from_node_id / to_node_id (carrying the same tempIds) go in one payload, and save_diagram.php's nodeIdMap resolves the refs server-side
  • Connectors created via Add related objects carry cmdb_relationship_id for provenance back to the real CMDB row

Add Related Objects (the killer feature)

Select a placed node and click Add related objects in the detail panel footer. Modal lists every CMDB object connected to this one across three buckets:

Bucket Source Verb on the connector
This object β†’ others cmdb_object_relationships where this object is from_object_id The relationship verb (e.g. depends on, hosts)
Others β†’ this object cmdb_object_relationships where this object is to_object_id The inverse verb so it reads naturally from this POV
Referenced by properties cmdb_object_properties where value_object_id = this id The property name (e.g. Owner, Host Server)

Tick the rows you want, hit Add N objects, and the selected objects place in a ring around the source β€” angle starts at 12 o'clock and walks clockwise; radius scales with count. Connectors auto-drawn in the correct direction for each relationship type. Already-on-canvas objects show a grey "on canvas" badge with the checkbox disabled.

The endpoint returns one row per (object, path) β€” so an object reachable via two paths surfaces as two tickable rows. Additions are deduplicated by cmdb_object_id. Property-ref connectors leave cmdb_relationship_id NULL and carry the property name as their label. On a read-only version the panel still shows, but the Add related objects button is disabled with a tooltip explaining why.

Detail Panel

Selects any placed node to open. Shows the node's icon, name, class, planned status, and a deep-link to the CMDB object page. Also lazy-fetches and renders every CMDB property that has a value on the bound object:

Property type Rendering
text Auto-detects HTTP/HTTPS URLs and linkifies them
number Locale-formatted with thousand separators
date Locale-formatted date
boolean Green Yes or grey No pill
dropdown Coloured pill picking up the option's CMDB colour with luminance-based text contrast
object_ref Pink-pill link straight to the referenced object's CMDB page (new tab)

Empty properties hidden so the panel stays tight. Add related objects button pinned to the bottom of the panel as a sticky footer so it's always reachable regardless of property count.

Planned Objects (Future-State Architecture)

If a CMDB object has is_planned = 1 (set on the CMDB object detail page), the node renders with:

  • Dashed amber border
  • Soft #fffbeb background tint
  • Italic amber label
  • Small PLANNED pill between the icon and the label

Lets you draw as-is and to-be on the same diagram without needing two separate ones. When the object goes live, flip the planned flag off in CMDB and the diagram restyles on next load β€” no edits needed.

Icon Library

The ~65-icon library lives in assets/js/network-mapper-icons.js, which ships a window.NM_ICONS map plus window.NM_ICON_META (label + category per icon), window.NM_ICON_CATEGORIES (display order / labels) and an nmRenderIcon(key, size, extra) helper. Twelve categories:

Category Icons
Compute & Servers server / server-rack / server-blade / server-tower / mainframe / vm / function / workstation
Databases database / database-cluster / database-cache
Storage storage / storage-san / storage-tape / backup
Networking network / router / switch / firewall / load-balancer / proxy / vpn / gateway / wireless-ap / modem / cdn / dns
Security shield / lock / key / ids / siem
Cloud cloud / cloud-private / cloud-public / cloud-hybrid / region
Containers container / container-pod / kubernetes / registry
Applications & Data application / service / website / api / microservice / queue / cache / dashboard
Endpoints laptop / mobile / tablet / iot / printer
Monitoring & Ops monitor / alert / log
People & Org person / team / org
Files & Generic document / folder / globe / mail / calendar / box

Feather-style 24Γ—24 viewBox, stroke 1.8, currentColor so they tint with any container. Unknown keys fall back to box. The full set is also seeded into cmdb_icons, so CMDB Classes settings can pick from the wider library when defining new classes. Multiple variants per concept (three server styles, three database styles, four cloud styles, etc.) exist precisely so the per-node icon override below can visually distinguish two objects of the same class.

Per-Node Icon Override

Each node defaults to its CMDB class's icon, but you can override per-node β€” useful when you want to distinguish two objects of the same class visually (e.g. Production MS SQL as a clustered-cylinder, Reporting Oracle as a single cylinder, both still bound to the Database Server class).

  • Select a node, click Change next to the Icon row in the detail panel
  • Picker modal shows ~65 icons in a 12-category grid with type-ahead search (matches icon key + human label)
  • Currently-used icon highlighted with a thicker cyan border
  • Click an icon to commit immediately (no separate Save button)
  • Reset clears the override and goes back to the class default

Stored as icon_override on network_diagram_nodes β€” a free-text VARCHAR(100), so any icon key works, not just seeded ones. If you pick the same icon as the class default, the override is stored as NULL rather than a redundant duplicate.

Page Size Guide

Page dropdown in the toolbar cycles between Off / A4 / A3 / A2 / Letter / Tabloid Γ— portrait / landscape. Picking a size renders a subtle dashed cyan outline at the actual paper dimensions (96 DPI). Useful for composing diagrams inside the printable area before sharing / exporting.

  • Persisted per-diagram (paper_size + paper_orientation columns)
  • Carried forward on save-as-new-version so analysts don't re-pick on every fork
  • Corner text label names the paper (e.g. A3 landscape) so the active size is visible at a glance
  • The outline renders inside the SVG layer with a soft white fill that lets the dot-grid bleed through, so on-page vs off-page is visually distinct
  • Drives the export bounds β€” see PNG / PDF Export below
  • Read-only versions can view the outline but can't change it (rejected with a toast)

Header / Footer Branding Overlay

Six-slot strip (left / centre / right, top + bottom) rendered along the page outline edges. Renders the org logo, title, author, version, modified date β€” same six anchors as a Word header / footer.

Org-wide defaults configured at System β†’ Branding (logo upload + the six text slots). Per-diagram override via the Branding button in the editor toolbar β€” modal shows the org defaults as input placeholders so you see what you're overriding.

Template tokens resolved client-side at render time:

Token Renders
{{logo}} The org-wide uploaded logo as an <img>
{{title}} Diagram title
{{author}} Author's full name
{{version}} Version label
{{modified}} Locale-formatted updated datetime

Tokens are HTML-escaped at substitution so a diagram named <script> can't break out into JS. The logo renders as an <img> with max-height 28px so it sits neatly inside the strip. Requires a page size to be set (the page outline gives the strip its anchor points). Empty slots in the override modal mean explicit blank (overrides the org default with nothing); Reset clears all six overrides back to NULL so they inherit again. Per-diagram overrides live on six nullable VARCHAR(200) columns on network_diagrams and are carried forward on save-as-new-version.

Zoom & Present Mode

Zoom controls β€” segmented 4-button group in the toolbar: βˆ’ zoom out / current level (click to reset to 100%) / + zoom in / Fit (scales to fit the page outline if set, else the bounding box of placed nodes + 40px padding). Discrete steps: 25 / 50 / 75 / 100 / 125 / 150 / 200 / 300%.

Present mode β€” Present button hides everything except the canvas (toolbar, palette, detail panel, meta row, read-only banner) so screen-sharing the diagram in a meeting doesn't reveal the editor chrome. A floating Exit Present pill (top-right) leaves it; Esc also exits regardless of focus. Also hides the module nav bar and tight-fits the diagram edge-to-edge. F11 takes the browser fullscreen for a true edge-to-edge view. Restores the user's previous zoom + scroll on exit.

Auto-Centre

One-click button that recentres every node so the diagram's bounding box sits centred on the selected paper size. Computes the bbox of placed nodes including the label that hangs below each icon (so optical centre matches visual centre), reads the page rectangle, computes the shift, snaps the delta to 20px (preserving the grid), and applies it to every node. Persistent β€” mutates node coordinates so the centring survives save / reload and is captured by exports.

PNG / PDF Export

PNG and PDF buttons in the toolbar produce WYSIWYG snapshots. Capture clips exactly to the page rectangle if a paper size is set, otherwise crops to the bounding box of placed nodes plus 40px padding. Branding header / footer, page outline, connectors, node icons, and labels all render in the output exactly as they appear on screen.

  • html2canvas 1.4.1 (~200 KB) for rasterisation + jsPDF 2.5.2 (~360 KB) for PDF wrapping β€” both vendored locally at assets/js/vendor/ so the feature works offline
  • 2Γ— scale for crisp output on retina screens and during presentations
  • PDFs use the actual paper size + orientation so the file opens at the right physical dimensions for printing
  • Filename slugifies the diagram title + version label (e.g. Production Network v2 β†’ production-network-v2.png)
  • Selection rings / connector cyan-highlights are hidden during capture so they don't bleed into the output (via an .is-exporting class that also hides edge handles and the empty-state placeholder)
  • The capture pass stashes the current zoom / scroll / selection, resets zoom to 1Γ— so the rasteriser captures at native resolution, then restores everything afterwards
  • Refuses to export an empty diagram with no paper size set (toast: "Nothing to export β€” place some nodes or set a page size first")
  • Read-only versions can export too β€” it's a view-only operation

Versioning

Every diagram is part of a linear version chain. The leaf (no children) is the editable current version; older nodes in the chain are read-only history.

  • Save as new version clones the current state forward into a new editable leaf and demotes the old leaf to historical. It auto-saves first if the canvas is dirty (since create_version.php clones from the persisted state), then opens a modal pre-filled with the current diagram's metadata and a suggested incremented label β€” the trailing integer in the version label bumps automatically (v3 β†’ v4)
  • Versions dropdown in the toolbar lists the chain β€” newest first, each row showing author + date, with a cyan Viewing pill on the current view, cyan Current pill on the editable leaf, amber Read-only pill on the rest. Rows are real <a href> links so middle-click / Ctrl-click opens in a new tab for side-by-side comparison
  • No branching β€” a parent can have at most one child; the chain is strictly linear. Need to explore an alternative? Create a separate diagram

Read-only versions render an amber banner across the top, disable Save + Save-as-new-version, and gate markDirty() so even programmatic edits can't dirty them. The Branding modal also can't open on a historical version.

Saving

Two modes:

  • Autosave (toggle in the toolbar) β€” saves ~2 seconds after your last edit. Word-style status indicator cycles through Unsaved / Saving… / βœ“ Saved / ⚠ Save failed β€” retry / Autosave off. Toggle state persisted per-analyst in user_preferences under the network_mapper_autosave key
  • Manual save β€” Save button or Ctrl+S. Works regardless of autosave state

Autosave defers if you're mid-drag so a save never clobbers a drag in progress. Browser beforeunload prompts on navigate if there are unsaved changes.

Help (network-mapper/help.php)

Interactive help guide with sticky scroll-spy sidebar nav and 11 sections covering the end-to-end workflow β€” overview, creating a diagram, placing nodes, drawing connectors, adding related objects (highlighted as the killer feature), planned objects, page size guide, header & footer, versioning, saving, and quick tips. Cyan branding throughout.

Data Model

3 tables, all prefixed network_diagram_:

Table Purpose
network_diagrams One row per version. parent_diagram_id self-FK chains versions; the leaf (no children) is current. Holds title, description, version_label, paper_size, paper_orientation, the 6 header / footer override columns
network_diagram_nodes Node placements. diagram_id + cmdb_object_id binding + x / y position + size enum (small / medium / large) + icon_override
network_diagram_connectors Edges. diagram_id + from_node_id / to_node_id + optional cmdb_relationship_id (provenance) + label + line_style

Foreign keys cascade β€” delete a diagram and its nodes + connectors go too; delete a node and its incident connectors go too. The parent_diagram_id FK uses ON DELETE SET NULL so deleting one version doesn't cascade the chain.

API Endpoints (api/network-mapper/)

Endpoint Purpose
list_diagrams.php Leaf-only diagram list with per-row node / connector / version counts
list_versions.php Root-to-leaf chain for a given diagram, each flagged is_current
get_diagram.php Single version hydrated β€” nodes carry CMDB object name / class / icon / planned flag; connectors include CMDB relationship link
create_diagram.php POST title / description / version_label
create_version.php Clones nodes + connectors forward into a new diagram row chained to parent. Refuses to fork an already-forked parent (no branching in v1)
save_diagram.php Transactional delete + reinsert with temp→real node id mapping. Refuses non-leaf versions. Per-field partial saves supported
delete_diagram.php Single version delete β€” older versions preserved via the SET NULL parent FK
get_related_objects.php Powers Add related objects β€” returns the three buckets (outgoing / incoming / property-ref) for a given source object

list_diagrams.php finds the leaves with WHERE id NOT IN (SELECT parent_diagram_id …) β€” a leaf is simply a version no other version points at as its parent.

⚠️ **GitHub.com Fallback** ⚠️