feat(ui): PrimeVue 4 migration + remove @featherds/styles SCSS build dependency#8
Open
cnewkirk wants to merge 698 commits into
Open
feat(ui): PrimeVue 4 migration + remove @featherds/styles SCSS build dependency#8cnewkirk wants to merge 698 commits into
cnewkirk wants to merge 698 commits into
Conversation
added 30 commits
April 12, 2026 21:08
…migration shim Replaces flat WidgetConfig with per-type discriminated union interfaces (summary, table, graph, node-status, availability), bumps CONFIG_VERSION to 3, adds DashboardTimeRange + resolveTimeRange, and adds a v2→v3 migration shim in loadConfig/loadFromServer.
…Libre; fetch nodes/alarms on mount
…protocol - build-dark-mode-overlay.sh: sed-patch connect-src to allow tiles.opennms.org, openstreetmap.org, and opentopomap.org, plus worker-src 'self' blob: so MapLibre's Web Workers load. The overlay script is the only path that actually reaches the running container; editing webapp/WEB-INF/web.xml alone is a dead letter (48e44da, 47f013b confirmed this the hard way). - CLAUDE.md: add container-freshness check to the session-start protocol and spell out that deploy-to-container.sh only covers ui/src/ — anything touching JSPs, jars, features, or config XML needs a full overlay rebuild.
Dark-mode outlined severity styling was unreadable on the softer light-mode surfaces (warning/minor amber on light gray = invisible). Move the light-mode overrides into the global opennms-feather-styles.scss so they apply to both SeverityBadge and the Alarms filter chips without fighting Vue's scoped-CSS transformer, which silently drops descendant selectors inside :global(X) .child blocks. Also deepen the light-mode surface palette (--feather-surface plus the full --feather-elevation-background-* stack that Feather DS hardcodes to #fff) and boost border/shade opacity so card edges and row dividers remain visible against the darker gray-blue background. SummaryWidget's warning KPI value gets a dedicated dark-amber color since #fbe947 is unreadable on light.
…oval, nav reorganization)
…le imports; drop redundant content height
…tence Create the structural shell of SideNav.vue with: - Collapse state managed locally with localStorage persistence - Toggle button with PrimeIcons (pi-angle-left/pi-angle-right) - CSS Grid integration via sidenav-collapsed class on .app-shell - Accessible aria-expanded and aria-label attributes Also add placeholder TopBar.vue to satisfy App.vue imports. Task 3 of 11: Shell redesign — collapse mechanics only, nav items added in Task 4.
…etConfigDialog to thin shell Creates ui/src/components/Dashboard/config/ with SummaryWidgetConfigForm, TableWidgetConfigForm, GraphWidgetConfigForm (stub), NodeStatusWidgetConfigForm, and AvailabilityWidgetConfigForm using PrimeVue 4 inputs. WidgetConfigDialog is now a thin shell that dispatches to the correct form based on widget type, using typed computed refs to avoid Vue template TS cast limitations.
…per test; assert classList.toggle
Replaces collapse-only skeleton with full nav implementation: three collapsible sections (Monitor, Network, Administration), plugin items from pluginStore, auto-open on active route, and per-section accordion. Applies Task 3 review fixes: no-op width transition removed, corrected aria-expanded placement on toggle button, rgba hover backgrounds, and focus-visible outlines on all interactive elements.
…nt boundary - autoOpenSection: use exact match or startsWith(item.to + '/') to avoid false prefix matches (e.g. /nodes hitting /node-details) - Admin section subheaders now carry visible guards matching their children: System/MonitoringConfig/Notifications → adminRole, Tools → adminRole||dcbRole Provisioning left ungated (has two ungated child items) - Remove unnecessary dynamic binding :title="'Plugins'" → title="Plugins"
…n routes - Replace FeatherIcon/SearchIcon in Search.vue with inline SVG - Overwrite TopBar.vue stub with full PrimeVue implementation (logo, search, add-node button, datetime, notifications, user menu, theme toggle) - Wire expanded prop for UserNotificationsMenuItem and UserSelfServiceMenuItem - Add /provision/quick-add and /provision/requisitions stub routes to router
…ingle dropdown Co-Authored-By: Chance Newkirk <chance.newkirk+github@pm.me>
…Popover migration
…PrimeVue Wire menu/App.vue to Shell/TopBar.vue and Shell/SideNav.vue; remove dead Feather DS FeatherAppBar/FeatherSidenav components and their imports.
added 30 commits
May 2, 2026 13:04
Admin hub: remove page-level surface override so cards get real elevation contrast against the background; add border-light border and slightly rounded corners to AdminCard. UserAccount: new Vue page at /account with change-password form using the existing REST service. UserSelfServiceMenuItem now routes to /account via Vue router instead of navigating to the legacy selfService JSP. Assisted-By: Claude <noreply@anthropic.com>
The lab containers persist across test-opennms rebuilds, but the test container's /opt/opennms/etc/imports/Topology-Lab.xml is wiped every podman rm/run cycle — leaving the lab orphaned (containers up, OpenNMS unaware) and the UI with a near-empty state until reattached. - .topology-lab/Topology-Lab.xml: single-source requisition XML - provision-topology-lab.sh: idempotent reattach script — copies the XML into test-opennms, triggers import, patches snmpifspeed back to 1 Gbps after provisiond's racy initial scan, cleans up EnLinkd auto-discovered duplicates, reloads EnLinkd - start-topology-lab.sh phase 7 now calls provision-topology-lab.sh instead of duplicating ~130 lines of inline XML and provisioning logic — single source of truth - CLAUDE.md: both checks (lab containers up + Topology-Lab requisition present) are now default session-start steps for any UI work, not gated on "is this a topology task?" Includes the rebuild-wipe gotcha - EnlinkdLinksTab.vue: PanelLoader straggler missed from the earlier ProgressSpinner sweep
…+ JSP redirects Replaces 6 legacy JSPs with Vue SPA pages: Help (doc/community/support links), Support (commercial + community cards), SystemStatus (daemon status from /rest/info), About (system info from /api/v2/system/about), and RtcCategory (nodes-in-category table with active outage cross-reference). Adds systemInfoService.ts, 5 new routes, legacy route map entries, and JSP redirect scriptlets for all 6 paths.
…ing, scope outages to category
… + JSP redirects - Domain D: KscReports list + KscReportDetail with graph image rendering - Domain F: Reports list with filter, links to legacy report runner - Domain C: Notifications list + NotificationDetail with acknowledge support - Domain B: Assets node browser + AssetEdit form + Hardware inventory viewer - 4 service files: kscReportService, reportService, notificationInboxService, assetService - 8 router entries added before /account - 5 JSP redirects: KSC/index, report/index, notification/index, asset/index, hardware/list Assisted-By: Claude Sonnet 4.6
Add global PrimeVue (unstyled) to tests/setup.ts so all component tests
that mount PrimeVue widgets (InputText, Button, Menu, Paginator) get the
required $primevue.config injection without style-sheet DOM errors.
EventConfigEventTable.vue: add data-property attrs to sortable th
elements and defineExpose({ sortChanged, sort, columns, expandedRows })
so test assertions can drive sort state directly.
EventConfigEventTable.test.ts: align all 64 assertions to the current
PrimeVue-based component API — th selectors replace SortHeader finders,
Menu model prop replaces MenuItem DOM stub traversal, Paginator @page
event replaces update:modelValue, and icon names use pi pi-* prefix.
EmptyList.vue: add data-test="empty-list" to root div for test
findability.
Assisted-By: Claude Sonnet 4.6
Includes help, about, status, support, rtc/index, rtc/category, KSC/index, report/index, notification/index, and hardware/list redirects in the staging and Dockerfile COPY sections so they survive container rebuilds. All new JSPs now return HTTP 302 to their respective /ui/* routes. rtc/category.jsp preserves the ?category= query parameter. Assisted-By: Claude Sonnet 4.6
Browser default body { margin: 8px } was never overridden,
producing a visible white gap on left, right, and top in all themes.
Assisted-By: Claude Sonnet 4.6
PrimeVue Aura's {list.option.focus.background} resolves to {slate.100}
(#f1f5f9) which is near-white and invisible on our surface, and under
certain specificity conditions can render as a dark/black bar instead.
Replace with a theme-neutral rgba(0,0,0,0.08) overlay under
html:not(.open-dark) to guarantee a visible tint on any light surface.
Assisted-By: Claude Sonnet 4.6
All six dashboard widgets (Alarms, Outages, Nodes, NodeStatus, Availability, Summary) previously rendered empty/default states immediately on mount before their AJAX calls returned. This made the dashboard flash "All services up", "100% availability", or "No nodes found" briefly before real data arrived. Each widget now initialises isLoading=true, renders PanelLoader while the fetch is in-flight, and reveals content (or the real empty-state) only in the finally block. WidgetFrame still owns the manual-refresh spinner, so the two concerns don't overlap. Assisted-By: Claude Sonnet 4.6
46 JSPs that still rendered legacy content now issue a sendRedirect to the corresponding Vue route on first request, so bookmarks and server-provided links land in the correct Vue page. Simple redirects: account/selfService/*, roles/*, application/index.jsp, report/database/index.jsp, admin/snmpmanage.jsp, admin/nodelabel.jsp, all admin/discovery/add-*.jsp and config-done/scan-done, all admin/notification/wizard sub-pages, admin/nodemanagement/* pages, admin/sched-outages/editoutage.jsp, admin/product-update-enrollment, alarm|event/severity.jsp, asset/nodelist.jsp, and action-result confirmation pages (deleteNodesFinish, manageNodesFinish, interfaceAdded, interfaceDeleted, serviceDeleted, postevent). Parameterised redirects (preserve ID from request param): notification/detail.jsp → /ui/notification/:id asset/modify.jsp → /ui/asset/:nodeId/edit admin/nodelabel.jsp → /ui/node/:nodeId JSP changes require overlay image rebuild to take effect. Assisted-By: Claude Sonnet 4.6
Previously had 22 entries covering only the most common menu paths. Now maps all 65+ known server menu URLs to their Vue equivalents, covering monitoring, inventory, admin, account, and tools sections. The file is reference documentation and is also used as a lookup table by any future caller of resolveVueRoute(). The SideNav uses static router-link entries directly, so this file is not on the hot navigation path. Assisted-By: Claude Sonnet 4.6
…hout Dashboard widgets: add position:relative to WidgetFrame.widget-body and switch widget PanelLoaders to overlay mode so the spinner centers inside the card instead of appearing in the upper-left corner. Full-page loaders: replace "Loading…" text in ResourceGraphsPanel, NetworkTab, NodeDetails, InterfaceDetail, OutageDetail, NotificationDetail, AssetEdit, ScheduledOutages, GeocoderConfig, SystemConfig, ThresholdConfig with centered PanelLoader wrappers. Assisted-By: Claude Sonnet 4.6
Replace the manually-maintained list of individual cp/COPY commands with a grep-based loop that automatically discovers every JSP/HTM file in the source tree that contains sendRedirect. The Dockerfile COPY lines are generated dynamically from the staged overlay directory using a find() command substitution inside the heredoc. Before this change, only ~30 JSPs were in the overlay; ~80 committed sendRedirect files (admin/*, element/*, account/*, alarm/*, asset/*, etc.) were never staged and therefore never activated in the test container. This closes the gap without requiring manual maintenance whenever new redirect JSPs are added. Assisted-By: Claude Sonnet 4.6
28 tests covering simple path redirects, parameterized detail-page redirects, POST pass-through, AJAX pass-through, and REST/Vue fast-path pass-through. Class under test does not exist yet. Assisted-By: Claude Sonnet 4.6
Replaces per-JSP sendRedirect stubs and fills the Spring MVC list-route gap (alarm/list.htm, event/list.htm, outage/list.htm, notification/browse, element/service.jsp) with a single Filter that fires before any JSP or DispatcherServlet execution. Covers 80+ simple paths and 16 parameterized patterns (node detail, interface, alarm/event/outage/notification detail, asset edit). Assisted-By: Claude Sonnet 4.6
…rity Filter runs after auth check, before StoreRequestProperties — avoids unnecessary processing for redirected requests. Assisted-By: Claude Sonnet 4.6
…tFilter Per-JSP sendRedirect calls are now dead code — the filter intercepts GET requests before any JSP executes. Removed all 126 pure-redirect stubs, including both top-level JSPs (about, admin, alarm, element, etc.) and WEB-INF/jsp view templates that contained nothing but redirect logic. Files retained: login.jsp, logoff.jsp, accessDenied.jsp, errors/, geomap/, heatmap/, trend/, rss.jsp, and any JSP with substantive non-redirect content. Assisted-By: Claude Sonnet 4.6
The overlay build patches web.xml in-place via sed/python rather than copying the source version (which would break CXF servlet mappings). Add a python3 RUN step that inserts the <filter> declaration before the first <filter-mapping> block and the <filter-mapping> after the springSecurityFilterChain mapping so auth runs before redirect logic. Assisted-By: Claude Sonnet 4.6
Both tests assumed list() returned a ModelAndView with query results. list() now redirects to Vue and returns null. Replace with redirect verification. Assisted-By: Claude Sonnet 4.6
…ntrollerTest Three private helpers (getOnmsEvents, getAlarms, getEvents) and their associated imports were left behind when the old tests were replaced. No test references them. Assisted-By: Claude Sonnet 4.6
…ering JSP createFavorite and deleteFavorite on AlarmFilterController and EventController called a private list() helper that rendered the legacy alarm/list and event/list JSP templates. Now they redirect to /ui/alarms and /ui/events, completing the Vue migration for these endpoints. Assisted-By: Claude Sonnet 4.6
OutageFilterController and NotificationFilterController rendered outage/list and notification/list JSP views. Replace handleRequestInternal with a direct redirect to /ui/outages and /ui/notifications. The LegacyRedirectFilter already intercepts GETs; this closes the POST path. Assisted-By: Claude Sonnet 4.6
Add 20 SIMPLE_REDIRECTS entries for ad-hoc graph wizard steps (adhoc2-4, chooseresource, forecast, nrtg, grafana, results), KSC report workflow (customReport, customView, customGraphEditDetails, formProc*), and trend views — all redirecting to /resource-graphs or /ksc-reports. 6 new tests verify representative redirects all pass. Assisted-By: Claude Sonnet 4.6
…ctFilter - 7 graph ad-hoc wizard JSPs (GET paths redirect, no forms remain) - 1 KSC customGraphChooseResource wizard JSP - 9 orphaned widget JSPs (geomap, heatmap-box, rtc, status-box, trend) - 2 orphaned JSON AJAX endpoints (sched-outages autocomplete) - 5 WEB-INF/jsp view templates whose controllers now redirect to Vue Assisted-By: Claude Sonnet 4.6
…ollers All four Spring MVC controllers now redirect to Vue SPA routes; the private list() overloads, query-parms builders, filter-callback helpers, backing fields, and unused imports that were only reachable from those dead paths have been removed. Spring XML property wiring for the dropped fields in OutageFilterController and NotificationFilterController has been stripped from dispatcher-servlet.xml. EventControllerTest setUp() no longer calls the removed setWebAlarmRepository() setter. Assisted-By: Claude Sonnet 4.6
…rTest Covers two previously untested filter branches: HEAD requests to a known legacy path should redirect (not pass through), and a mixed Accept header that includes both text/html and application/json should also redirect rather than being treated as an AJAX/API call. Assisted-By: Claude Sonnet 4.6
…ty removal NotificationFilterController and OutageFilterController had their successView/ defaultShortLimit/etc setters removed, but dispatcher-servlet.xml lives in the base image WEB-INF — not in the webapp jar. Without copying it, Jetty tries to inject the old properties into the stripped controllers and fails to start. Assisted-By: Claude Sonnet 4.6
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.
Summary
New files (icons feature)
Test plan
🤖 Generated with Claude Code