feat(ui): PrimeVue modernization alpha — shell, dashboard, events, topology, map, admin pages#4
Open
cnewkirk wants to merge 35 commits into
Open
feat(ui): PrimeVue modernization alpha — shell, dashboard, events, topology, map, admin pages#4cnewkirk wants to merge 35 commits into
cnewkirk wants to merge 35 commits into
Conversation
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
…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.
…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
cnewkirk
force-pushed
the
feat/ui-refactor
branch
from
April 16, 2026 16:37
55c7ef9 to
5727a4b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Alpha Developer Preview
What's in this alpha
Shell (100% PrimeVue)
SideNavwith collapse/expand toggle, localStorage persistence, and RBAC-gated admin sub-sectionsTopBar: quick-search, theme toggle (light/dark), user self-service menu (Popover), notifications--sidebar-width-expandedCSS variable in real timeMenubar.vue/SideMenu.vueremoval — zero Feather DS shell components remainDashboard (widgets + toolbar)
/dashboard) with drag-and-drop layoutEvents list (
/events)orderBy=eventTime(nottimeJSON alias);dataKeynotdata-keyTopology
LoadViewModal/SaveViewModal--feather-backgroundat runtime for both light and dark modeMap
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
open-light.cssandopen-dark.cssdeclare vars in:root; dark loads last and always wins. Fixed via comprehensivehtml:not(.open-dark)override block (surface, elevation ladder, text, borders, shade, clickable tokens).rgba()values instead ofcolor-mix()(unreliable with nested CSS var component patterns).color-mix()replaced with explicitrgba()+:global(html.open-dark .kpi-card--*)overrides using full selector chain (avoids Vue scoper stripping descendant selectors ontohtmlelement).What's NOT in this alpha
Local dev setup
Requires the dark-mode overlay container image (
build-dark-mode-overlay.sh).🤖 Generated with Claude Code