Skip to content

feat(ui): PrimeVue modernization alpha — shell, dashboard, events, topology, map, admin pages#4

Open
cnewkirk wants to merge 35 commits into
developfrom
feat/ui-refactor
Open

feat(ui): PrimeVue modernization alpha — shell, dashboard, events, topology, map, admin pages#4
cnewkirk wants to merge 35 commits into
developfrom
feat/ui-refactor

Conversation

@cnewkirk

Copy link
Copy Markdown
Owner

Alpha Developer Preview

This is an early developer preview — not production-ready. It demonstrates the modernization direction and is intended for review, feedback, and local testing. History will be squashed before any upstream submission.


What's in this alpha

Shell (100% PrimeVue)

  • CSS Grid skeleton: 56 px top bar row + variable sidebar column (no FeatherAppLayout)
  • PrimeVue SideNav with collapse/expand toggle, localStorage persistence, and RBAC-gated admin sub-sections
  • PrimeVue TopBar: quick-search, theme toggle (light/dark), user self-service menu (Popover), notifications
  • Sidebar resize handle drives --sidebar-width-expanded CSS variable in real time
  • Full Menubar.vue / SideMenu.vue removal — zero Feather DS shell components remain

Dashboard (widgets + toolbar)

  • Configurable widget dashboard (/dashboard) with drag-and-drop layout
  • PrimeVue toolbar: SplitButton add-widget menu and absolute/relative time range picker
  • Widget types: Summary KPI cards, Availability ring (PrimeVue Chart), Node Status donut (PrimeVue Chart), Perses graph panel, Alarm/outage counters
  • Per-type PrimeVue config dialog (thin shell pattern)
  • Config schema v3 with category filtering, threshold expressions, multi-series graph builder

Events list (/events)

  • PrimeVue DataTable with server-side lazy loading and pagination
  • Sortable columns: eventTime, severity, node, UEI
  • Severity badge with semantic color tokens
  • Fixed: orderBy=eventTime (not time JSON alias); dataKey not data-key

Topology

  • View persistence: named views saved/loaded/deleted via JAX-RS YAML backend
  • A/Z edge tooltip: interface data, remote MAC, ifSpeed, four-series bandwidth charts
  • Edit mode: create/load/save/delete views with LoadViewModal / SaveViewModal
  • Edge label halo reads --feather-background at runtime for both light and dark mode
  • Height calc corrected for 56 px topbar

Map

  • MapLibre GL JS replacing Leaflet/leaflet-markercluster
  • Removed MapLibre watermark; style URL wired to configurable tile source

Admin pages migrated (Phases 3a–3g)

JMX Config Generator, MIB Compiler, Node Detail, SNMP Config, Syslog Config, Provision, API Tokens (fork PR #3 open), and supporting admin hub links — all replaced with Vue 3 SPAs.

Feather DS / light+dark mode fixes

  • Both open-light.css and open-dark.css declare vars in :root; dark loads last and always wins. Fixed via comprehensive html:not(.open-dark) override block (surface, elevation ladder, text, borders, shade, clickable tokens).
  • Dark mode: Feather DS purple surface neutralized to zinc tones matching PrimeVue bridge.
  • Severity badges and filter chips: explicit rgba() values instead of color-mix() (unreliable with nested CSS var component patterns).
  • KPI cards: color-mix() replaced with explicit rgba() + :global(html.open-dark .kpi-card--*) overrides using full selector chain (avoids Vue scoper stripping descendant selectors onto html element).
  • PrimeVue bridge: sky-blue primary palette replacing default violet.

What's NOT in this alpha

  • Full test coverage (unit/e2e tests for new components incomplete)
  • Commit history is unsquashed iterative development — will be rebased before upstream PR
  • Several legacy JSP admin pages remain (Scheduled Outages, Requisitions, etc.)
  • Mobile / narrow-viewport responsive pass not done
  • Accessibility audit not complete

Local dev setup

# Bootstrap (first time only)
cd ui && mvn install -DskipTests -Prun-npm

# Build & deploy
cd ui && ./target/node/yarn/dist/bin/yarn build
./ui/deploy-to-container.sh <container-name>

Requires the dark-mode overlay container image (build-dark-mode-overlay.sh).


🤖 Generated with Claude Code

opennms-bamboo and others added 30 commits April 8, 2026 11:33
Full library of specs and plans covering: JMX config generator, node detail,
alarms list, outage migration, surveillance dashboard, topology lab, Perses
replacement (4 phases), dashboard drag-resize, weathermap, edge labels,
topology enhancements, app-wide design language, rounded-corners normalization,
topology time-travel, and test fixture seed script.
Switch to pnpm, upgrade Vite/Vitest/date-fns/Font Awesome, add yarn deploy
script, add test setup, patch flot-legend, add timeline-resize improvements,
and add dark-mode overlay build helper.
Add dark-mode.scss overlay with full token coverage, modern-ui.scss with
opinionated resets, Feather DS → MUI theme bridge for Perses panels, and
SCSS vars.scss with rounded-corner tokens and border-radius normalization.
Add Liquibase migrations for onms_dashboards (Perses persistence) and
topology_views (per-user saved views) in 35.0.5. Add OnmsDashboard and
TopologyView entities with Hibernate DAOs. Expose OnmsOutage.serviceName
as @transient field for API serialization.
…ons,

dashboard, surveillance views, wallboard config, and topology views

JmxConfigResource — async MBean detection + XML generation
MibCompilerResource — async MIB compile, event/data-collection generation
SnmpCollectionConfigResource / DataCollectionGroupsResource — read-write SNMP
DashboardRestService — Perses dashboard CRUD at /rest/dashboards
SurveillanceViewConfigRestService — surveillance view read-write
WallboardConfigRestService — wallboard config read-write
TopologyViewsRestService — per-user saved topology views with authorization
MenuProvider — server-side menu template with Vue SPA entry points
Register all resources in applicationContext-cxf-rest-v2.xml.
Add JSP redirects for: alarm/detail.htm, event/detail.jsp, outage/detail,
node.jsp, node list, dashboard.jsp, topology.jsp, graph/index.jsp,
jmxConfigGenerator.jsp, mibCompiler.jsp, manageSnmpCollections.jsp,
surveillanceViewsConfig.jsp, wallboardConfig.jsp, admin BSM pages,
manageEvents.jsp. Add Spring MVC controller for alarm detail redirect.
Update bootstrap.jsp and web.xml as needed.
…ions Vue SPAs

JmxConfigGenerator — 4-step wizard: connection, MBean detection, tree selection,
review/download. Async MBean detection polling with 120s timeout.
MibCompiler — MIB upload, compile, generate events/data-collection dialogs.
SnmpCollectionsConfig — tabbed view of SNMP collections and data collection groups
with inline editor. All backed by new REST APIs.
Dashboard — gridstack drag+resize layout, 4 widget types (alarms/nodes/outages/
summary), server-side persistence via DashboardRestService.
SurveillanceDashboard — full-featured surveillance grid with cell drill-down.
SurveillanceViewsConfig — row/column editor for surveillance view config.
WallboardConfig — dashlet-based wallboard configuration editor.
BusinessServicesAdmin — BSM graph editor with AddEdgeForm slide-over.
AlarmDetail — full alarm detail with acks, memos, journal, related alarms.
EventDetail — event detail with severity, UEI, parameters, node link.
OutageDetail / OutagesList — outage list with filtering + detail page.
All pages wired to router and redirected from legacy JSPs.
Phase 1 — OpenNMS Perses datasource plugin: QueryEditor, client,
fetchMeasurements with OpenNMS timestamps in ms, plugin registration.
Phase 2 — PersesPanel/PersesCanvas React mount composable; Feather→MUI theme bridge.
Phase 3 — ResourceGraphsPanel replacing Chart.js: ResourceSidebar, AttributeList,
QueryBuilder, CustomChart, PinnedGraphs, ResourceAccordion, RrdGraphConverter.
Phase 4 — Wire into NodeDetail, support CSV/JSON/XML export, hide-empty-rows toggle.
Consolidate alarms/events/outages into tabbed NodeActivityTab. Add EnLinkd
Links tab with physical-link-first row layout, protocol badge deduplication, and
IS-IS index resolution. Add ResourceGraphsPanel, PinnedGraphs, full availability
panel with IP grouping. Add AlarmsTable, InterfacesTabs with availability
rollup. Problems-first perspective toggle with per-node display mode.
…polish

AlarmsListTable — configurable columns with localStorage persistence, HTML badges,
severity filtering, router-link KPI cards.
SeverityBadge — shared severity badge component with consistent theming.
PerspectiveToggle — problems-first / all-nodes perspective with server-configurable default.
Common components — ClearSummary, CollapsibleSection, Pagination, StatusSummaryLine,
TableCard, MapAlarmsGrid, MapNodesGrid with router-links.
EventConfiguration — event config table and upload dialogs.
ZenithConnect — ZenithConnect registration result page.
SideMenu / Menubar — brand blue top bar, Vue SPA menu entries for all replaced
pages, correct Feather DS variables in light/dark mode.
Router — add routes for /topology, /alarms, /alarm/:id, /event/:id, /outage/:id,
/outages, /node/:id, /dashboard, /surveillance-dashboard, /surveillance-views-config,
/wallboard-config, /jmx-config, /mib-compiler, /snmp-collections, /bsm.
TypeScript types — mainMenu.d.ts, cytoscape-cxtmenu.d.ts, updated index.ts.
…ew system

Core topology:
- Cytoscape.js graph with multi-protocol edge collapsing, parallel colored edges,
  protocol color palette, user-defined links (create/delete via context menu)
- Rich node/edge detail panels with EnLinkd L2/L3 data
- Edge hover tooltip with protocol chips, utilization badge, link data fields
- Layer toggle compact dropdown, protocol legend, grid snap + align-to-grid
- Hierarchical layout with persistence

Weathermap overlay (weathermapStore):
- Polling SNMP interface utilization via measurementsService
- Real-time edge width/color/label by bandwidth utilization
- In/out rates and utilization % in tooltip

Edge labels (topologyViewStore):
- Per-user edge label visibility config (local port, remote port, IP, MAC, speed)
- EdgeLabelData from weathermapStore via LLDP/ARP/IP interface lookups
- humanize() field name formatting, cidrUtils for CIDR filter
- composeEdgeLabel / applyEdgeLabels in useTopology

Topology views:
- topologyViewStore: save/load/delete private, shared, and global views
- Server-side persistence via TopologyViewsRestService
- Filter panel: category, CIDR, and name filters
- Views panel: per-user saved views with admin global view management
- Global view and personal filter defaults applied on page load
- prettifyProtocol normalization throughout (Isis→IS-IS, Lldp→LLDP, etc.)
- L2/L3 correlation gap documented in topologyStore TODO
Bash script that spins up a podman network of FRR nodes with IS-IS,
attaches OpenNMS, imports requisition, triggers EnLinkd rescan, and
verifies convergence. Includes teardown helper.
Adds selectedTime ref (null = live) and setTime async action to
weathermapStore. Historical mode cancels auto-refresh and fetches a
single snapshot at the given time; resetting to null resumes polling.
Passes selectedTime through to fetchInterfaceUtilization.
Add TopologyTimeControl component between the toolbar and graph canvas,
bind it to wmStore.selectedTime via a computed v-model, and extend the
topology-page height calc from 120px to 160px to accommodate the new bar.
Import useWeathermapStore into TopologyGraph.vue and overlay a pill-shaped
watermark in the top-left corner of the canvas whenever wmStore.selectedTime
is non-null, showing the formatted historical timestamp.
Renders Chart.js sparklines for interface utilization, errors, and discards
inside the edge hover tooltip. Fetches 2-hour time series data per endpoint,
cancels in-flight requests on unmount, and re-fetches in live mode on refresh.
runLayout() only called cy.fit() on the preset path. The breadthfirst
and cose paths positioned nodes but left the viewport untouched, causing
nodes to render off-screen and disappear after layout. Regression was
exposed by the TopologyTimeControl addition reducing canvas height by 40px.
Topology weathermap improvements:
- Fetch utilization from BOTH endpoints via LLDP-correlated interfaces;
  EdgeUtil now carries src/tgt EdgeEndpointUtil so the tooltip shows
  per-endpoint in/out rates and utilization badges
- Idle links (0 bps with weathermap data) render teal; full traffic-light
  scale: teal → green → yellow → orange → red
- Edge tooltip: node names replace generic (source)/(target) labels;
  RX/TX replace directional arrows; localMac ↔ remoteMac row
- TopologyLegend: floating bottom-left panel with color swatches,
  protocol swatch, and reference-bandwidth selector; collapse/dismiss
  with localStorage persistence
- referenceBps in weathermapStore: overrides ifSpeed as utilization
  denominator for CIR-based or lab-calibrated display

Lab ifSpeed fix (Option C):
- Remove -M zebra_snmp from zebra_options so net-snmp's built-in
  IF-MIB module handles interface data (zebra AgentX subagent was
  bypassing snmpd override directives)
- Add `interface eth1/eth2/eth3 6 100000000` to snmpd.conf so
  data-plane interfaces report 100 Mbps instead of 10 Gbps;
  load-gen --max-mbps 100 now authentically exercises all five
  utilization color bands
- load-gen.py: add --bidir to iperf3 so both ifHCInOctets and
  ifHCOutOctets increment on each endpoint
When collectd hasn't yet collected for an interface (e.g. after a
container rebuild that changes MAC addresses), fetchInterfaceTimeSeries
returns empty arrays and Chart.js renders a blank canvas.

Show "awaiting data…" instead of a blank/0bps chart block when
inBps.length === 0.  Charts render as soon as data arrives.

Also remove the duplicate label guard in the chart creation watcher
(hasData check is now the single source of truth).
- fetchInterfaceUtilization: 5-min window/step → 90s window + 30s step;
  first valid rate now visible after 2 collectd samples (~60s) instead of
  waiting for a full 5-minute RRD consolidation period
- TopologyEdgeGraphs sparklines: step 60s → 30s to match finer resolution
- weathermapStore pollInterval: 60s → 30s to stay in sync with collectd
cnewkirk added 4 commits April 9, 2026 16:28
…terval

Add a module-level TTL cache in measurementsService.ts.  End timestamps
are floor-aligned to the step boundary so multiple callers within the same
collection window share the same cache key.  TTL equals one step (30s),
so the cache expires exactly when new data becomes available.

Benefits:
- fetchInterfaceUtilization: all 12 per-refresh calls for a 6-edge topology
  de-duplicate to at most one network request per unique interface per step
- fetchInterfaceTimeSeries / fetchInterfaceErrorsDiscards: repeated tooltip
  hovers over the same edge serve from cache without re-fetching 2h of data
Two fixes to the test harness so the weathermap exercises all five
utilization bands instead of capping at ~40%:

1. load-gen.py: Replace UDP --bidir (which had 50-80% packet loss on the
   reverse stream) with two independent TCP flows per link — one forward
   (spine→leaf) and one reverse (leaf→spine) using dedicated server ports
   5301-5306 on the spines.  Both ifHCInOctets and ifHCOutOctets now
   increment meaningfully on every data-plane interface.

2. start-topology-lab.sh: Add Phase 5b that patches the running OpenNMS
   test container before provisioning:
   - collectd SNMP interval: 300s → 30s
   - datacollection RRD step: 300s → 30s (so new RRD files are created at
     30s resolution and the measurements API returns per-sample data)
   - purges stale Topology-Lab RRD files so they get recreated at the
     new step on first collection
   - triggers collectd reload via REST event
Increases the synthetic link capacity from 100 Mbps to 1 Gbps:
- snmpd.conf interface directives: 100000000 → 1000000000 bps
- load-gen start args: --max-mbps 100 → --max-mbps 1000

Virtual veth pairs handle multi-Gbps without issue on Apple Silicon.
The weathermap now displays realistic Gbps-scale bandwidth numbers in
sparkline legends and edge tooltips while exercising the same
utilization band range (2%–98%).
Two root causes for weathermap showing <10% utilization:

1. eth0 (management) not overridden: All virtio-net interfaces default to
   10 Gbps in the kernel. The snmpd.conf only overrode eth1/eth2/eth3.
   pickBestInterface() selects the highest-speed oper-up interface, so it
   picked eth0 (10 Gbps) instead of a data-plane interface. Added
   'interface eth0 6 1000000000' to cap it at 1 Gbps too.

2. Provisiond scans ifSpeed at startup before the override stabilizes,
   writing 10 Gbps to the DB. Added a post-import sleep+SQL patch in
   Phase 6 to correct snmpifspeed to 1 Gbps after the initial scan
   completes.

Also: purge stale nodes from prior foreign-source name variants
('topology-lab' lowercase vs 'Topology-Lab') in Phase 5b to prevent
duplicate nodes appearing in the topology view.
@github-actions github-actions Bot added the docs label Apr 13, 2026
…reness

Shift red threshold from 90% to 80%: TCP sawtooth congestion and
microbursts start causing buffer drops well before saturation.

Old:  green <50  yellow <75  orange <90  red ≥90
New:  green <50  yellow <70  orange <80  red ≥80
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants