Skip to content

Conversation

@PaulJouvanceau
Copy link
Contributor

This PR introduces major updates to the EventLogger – several UI/UX refinements across the application – a significant increase in automated test coverage – and key fixes related to OIDC authentication and session management

EventLogger improvements:

-Added collapsible log entries with dense JSON view

-Added syntax highlighting for JSON data

-Removed redundant _rawEvent fields

-Added subscription info and interactive subscription management

-Updated event filter dropdown to show only received event types

-Overhauled the subscription system with delayed handling

UI/UX updates:

-Redesigned the WhoAmI page and simplified the NavBar

-Applied a full-width layout across components

-Improved NavBar accessibility and layout

-Added a secondary color to the MUI theme

-Removed global gutters and ensured #root fills the viewport

-Added ObjectDetail, NodeCard, and HeaderSection components

OIDC and authentication:

-Configured silent renew with a dedicated endpoint and iframe-based flow

-Attempt silent renew on expired tokens before logout

-Properly handle expired tokens when the app resumes or when the tab becomes visible

-Added Jest tests for the SilentRenew component

Testing:

-Improved test coverage for EventLogger, eventSourceManager, App, WhoAmI, ObjectDetails, and others

Misc:

-Replaced WarningAmberIcon with PriorityHighIcon

…eview

- Introduced expandable/collapsible log items using `ExpandMore` icon.
- Added `expandedLogIds` state to track expanded entries.
- Display dense (compact) JSON when collapsed and pretty-printed JSON when expanded.
- Updated drawer height, resizer, and styling for better readability.
- Simplified event log filtering and ensured safe handling of undefined logs.
- Minor UI improvements: padding, max-height, and cursor feedback on log items.
…e and expanded modes

- Replace plain JSON display with syntax-highlighted JSON using HTML spans
- Implement `syntaxHighlightJSON` function for colorizing JSON strings
- Add `JSONView` component to handle both dense and formatted JSON rendering
- Introduce color scheme for different JSON elements:
  - Keys: primary blue with bold weight
  - Strings: success green
  - Numbers: info blue with medium weight
  - Booleans: warning orange with bold weight
  - Null values: grey with bold weight
- Apply consistent styling to both collapsed (dense) and expanded (formatted) views
- Add global CSS styles for JSON syntax highlighting classes
- Improve visual hierarchy with background colors and transitions
- Maintain all existing functionality while enhancing readability

The coloration makes it easier to quickly identify data types and structure in event logs, improving debugging efficiency.
…ngs and unprovisioned states

- Unified warning and "not provisioned" icons across the entire UI
- Affected components:
  • Objects
  • HeaderSection
  • NodeCard
  • NavBar
- Now consistently uses PriorityHighIcon:
  • orange for warn status
  • red for unprovisioned
Ensures visual coherence with the rest of the interface
- Move Logout button from NavBar to WhoAmI page for better UX
- Replace text "Who Am I" button with icon-only in NavBar
- Remove app version display from NavBar
- Enhance WhoAmI page with modern card-based layout:
  - Split into two main panels: User Information and Server Information
  - Add connected node display with daemon nodename
  - Show application version in dedicated server panel
  - Improve visual hierarchy with icons and better spacing
  - Add hover effects and responsive grid layout
- Update authentication labels for consistency ("Auth Method" instead of "Authentication Method")
- Maintain all existing functionality while improving visual design
Increase branch coverage by adding missing tests:
- Skip fetchNodes when no authToken exists
- Fallback to cached/Unknown appVersion when GitHub API fails
- Handle JSON parsing error in WhoAmI fetch
These tests cover previously untested branches in WhoAmI.jsx
- Filter out _rawEvent from displayed JSON data
- Exclude _rawEvent from search functionality
- Use filtered data in both collapsed and expanded views
- Improve readability by eliminating redundant data duplication
- Add comprehensive test cases for edge scenarios and error handling
- Improve test reliability with proper async/await patterns and userEvent
- Add tests for console dialog interactions including URL handling
- Enhance resource action filtering tests with various resource types
- Add tests for drawer resize functionality with mouse and touch events
- Improve component unmount handling during async operations
- Add tests for config update subscriptions and error scenarios
- Enhance provisioned state parsing tests with comprehensive coverage
- Add tests for batch action flows and selection toggling
- Improve test organization and remove redundant code
- Add proper cleanup for event listeners and mocks
- Enhance getFilteredResourceActions tests with all resource type branches
- Add tests for getResourceType with various node data structures
- Improve fetch error handling tests with network failure scenarios
- Extend theme palette with secondary color configuration
- Use grey[600] as main secondary color with white contrast text
- Maintain existing primary color and all other theme settings
…ents

This final commit completes the comprehensive full-width layout redesign
by extending the modifications to the NavBar component and providing a
complete summary of all changes made.

Components Modified in this Series:

Layout Foundation:
- NavBar: Full-width navigation with proper alignment
- Objects: Complete full-width table layout
- Namespaces: Expanded namespace overview
- Heartbeats: Full-width heartbeat monitoring
- Pools: Comprehensive storage pool display
- Network: Network overview and details panels
- NetworkDetails: Detailed network information
- NodesTable: Full-width node management interface
- ObjectDetails: Enhanced object detail view
- ClusterOverview: Complete dashboard layout
- ClusterStatGrids: Supporting grid components

Key Technical Changes:
- Set width to 100vw for complete viewport coverage
- Removed all external margins and padding (margin: 0, padding: 0)
- Applied consistent border styling (2px solid divider)
- Maintained box-shadow consistency (level 3)
- Preserved internal content spacing for readability
- Ensured responsive behavior across all screen sizes
- Added proper box-sizing: border-box for layout consistency

Design System Consistency:
- Unified visual hierarchy across all pages
- Maintained interactive elements and hover states
- Preserved accessibility standards and ARIA labels
- Consistent color schemes and typography
- Cohesive navigation experience

The implementation now provides a seamless, immersive user experience
with maximum information density while eliminating visual clutter and
wasted space. All components now utilize the full viewport width
creating a modern, professional interface that enhances usability and
information accessibility.
- Fix NavBar width to span full viewport by adding width: "100vw" and proper box sizing
- Simplify Menu component by removing complex animations and custom styles
- Improve breadcrumb accessibility by decoding URI components in aria-labels
- Remove unused Logout import from AuthProvider
- Streamline button hover styles for consistency
- Ensure proper error handling for fetchNodes with robust function checks
- Maintain breadcrumb functionality while improving test compatibility

The NavBar now properly occupies the full viewport width while maintaining all existing functionality and improving accessibility.
- Add compact subscription information chip showing active event subscriptions
- Display subscribed event types count and object name when provided
- Maintain English language consistency throughout the component
- Ensure minimal UI space usage with compact chip design
- Preserve all existing functionality and test compatibility
- Fix test conflicts by ensuring JSON content detection is specific to log entries

The subscription info appears as a small chip below the header showing:
"Subscribed to: X event type(s) • object: name" when relevant props are provided.
- Add dynamic event subscription system with interactive chip component
- Implement subscription dialog with checkboxes for event type selection
- Separate display filtering from subscription management
- Add subscription state management with useState and useEffect hooks
- Include subscription actions (Subscribe to All, Unsubscribe from All, Reset to Default)
- Maintain existing display filtering functionality while adding subscription capabilities
- Use Settings icon for subscription management with tooltip guidance
- Log subscription changes for debugging and integration purposes
- Ensure backward compatibility with existing eventTypes prop behavior

The new subscription system allows users to:
- View current subscription status via interactive chip
- Manage event type subscriptions through dedicated dialog
- Control which event types to receive in the future
- Maintain display of historical events regardless of subscription changes
- Reset subscriptions to default configuration easily
- Add comprehensive test suite for NavBar component functionality
- Test breadcrumb generation for various path scenarios including:
  - Nested paths with URI encoded components
  - Network and objects specific path handling
  - Exclusion of 'cluster' segments from breadcrumb paths
- Test navigation menu behavior including:
  - Menu open/close functionality
  - Menu item selection and navigation
  - Selected state for current route
- Test object status monitoring and display:
  - Down and warn object count calculations
  - Tooltip functionality for status indicators
  - Object status from both event store and daemon data
- Test authentication and data fetching scenarios:
  - Token availability handling
  - fetchNodes function error handling
  - Loading states and cluster name display
- Test offline status detection and display
- Test edge cases including:
  - Undefined objects in status calculation
  - Missing instance monitor data
  - Invalid availability status handling
  - fetchNodes not being a function
  - Empty objects and object instances
- Ensure all branches and lines are covered including conditional logic for:
  - part !== "cluster" exclusion in breadcrumbs
  - fetchNodes function type checking
  - Object status validation and counting
… (not in subscription dialog)

- Changed the event type filter dropdown to use `availableEventTypes` (derived from actually received logs via `baseFilteredLogs`) instead of `allReceivedEventTypes`
- This ensures that the filter only displays event types for which at least one event has been received
- Event types with 0 received events are now hidden from the filter (as requested)
- Subscription dialog remains unchanged and continues to show all possible event types from the `eventTypes` prop, with their received count (0 if none)
- Minor cleanup: removed unused `allReceivedEventTypes` memo

Fixes the issue where users could select event types in the filter that had never been received (count = 0).
…ased renewal

- Add useRefreshToken: false to oidcConfiguration to disable refresh token usage by default
- Set silent_redirect_uri to dedicated /silent-renew endpoint instead of /auth-callback
- Create SilentRenew component that calls userManager.signinSilentCallback() for iframe-based silent renew
- Add /silent-renew route in App.jsx to handle the silent renew callback
- Enable oidc-client-ts DEBUG logging in OidcAuthContext for improved error diagnostics
- Expose window.oidcUserManager globally for backward compatibility with eventSourceManager
- Clean up window.oidcUserManager on OidcProvider unmount
- Update oidcConfiguration tests to expect useRefreshToken: false and /silent-renew URI

This resolves the 'Silent renew failed: ErrorResponse' issue by implementing proper iframe-based renewal
instead of attempting refresh token exchange which was failing with 400 errors.
- Create comprehensive test suite for SilentRenew component
- Test successful silent renew callback execution
- Test error handling scenarios:
  - UserManager unavailable
  - signinSilentCallback not a function
  - signinSilentCallback execution failure
- Test component rendering and default message
- Verify useEffect dependency behavior with userManager
- Mock external dependencies (useOidc context and logger utility)
- Ensure proper async/await handling with waitFor for callback tests
- Maintain test isolation with beforeEach cleanup
 -Add global CSS rules to remove default margins/padding from html/body/#root and set box-sizing to border-box for predictable layout.
 -Removes the small empty space around the site.
When an existing OIDC user is detected with an expired access token, attempt a silent renew via userManager.signinSilent() instead of immediately clearing auth state and redirecting. On successful renewal update the access token and auth state using onUserRefreshed; if the silent renew fails, the existing handleSilentRenewError flow will clear storage and redirect to the auth choice. This prevents unnecessary logouts when a silent token renewal is possible.
- Fixed missing signinSilent method in mockUserManager causing test failures
- Mocked useNavigate to properly test authentication redirect events
- Added tests for all uncovered branches in initializeOidcOnStartup
- Added tests for expired user silent renew failure scenarios
- Added tests for ProtectedRoute edge cases (null authChoice, OIDC without token)
- Added tests for handleCheckAuthOnResume with valid and invalid tokens
- Added tests for useEffect that saves authChoice to localStorage
- Added tests for custom event handling (om3:auth-redirect)
- Added tests for storage event with token updates
- Added tests for error handling in handleCheckAuthOnResume
- Added tests for token validation edge cases (malformed and expired tokens)
- Fixed storage event test by properly mocking localStorage responses
- All tests now use English naming conventions and comments

Key test categories:
1. OIDC initialization under various conditions
2. UserManager event handling and silent renew
3. ProtectedRoute validation logic
4. Visibility and focus-based authentication checks
5. Error boundary and exception handling
6. Event listener setup and cleanup
…anagement UI

- Implemented `ObjectDetail.jsx` to manage object details view, including:
  - Dynamic rendering of nodes and resources
  - Configuration fetching and display
  - Action dialogs for object, node, and resource operations
  - Event-driven updates using EventStore and SSE
  - Responsive logs drawer with resizable width
  - Console URL handling for resource access
- Created `NodeCard.jsx` for per-node resource display, featuring:
  - Accordion-based resource listing
  - Resource status indicators and logs
  - Batch and individual resource action menus
  - Support for encapsulated resources in containers
  - Responsive design with mobile-friendly layouts
- Added `HeaderSection.jsx` for object-level status and actions:
  - Displays object name, status, and global expect state
  - Provides action menu with permission checks
  - Handles Safari-specific Popper behavior
- Integrated with MUI for consistent styling and responsive design
- Added support for resource filtering based on type
- Included accessibility attributes (aria-labels) for key interactions
…ty change

Previously, when using OIDC authentication, the app would not detect an expired token when the tab regained focus or became visible again, because ProtectedRoute and resume checks were trusting the presence of a token without validating its expiration for OIDC flows.

Now, during visibilitychange/focus events (e.g. user switches back to the tab), we explicitly validate the JWT token using isTokenValid() even for OIDC mode. If the token is expired or invalid, the user is correctly redirected to /auth-choice.

This ensures consistent logout behavior across all authentication methods when tokens expire while the app is in the background.

Fixes a security and UX issue where users could remain falsely authenticated with an expired OIDC token.
…apply and safe empty-state handling

- Add proper subscription management: subscriptions now only apply when user clicks "Apply Subscriptions" in the dialog
- Introduce temporary state (tempSubscribedEventTypes) in the subscription dialog to allow checking/unchecking without immediate effect
- Fix critical bug: EventSource was not being recreated when all events were unsubscribed — now properly closes and reopens connection with updated filters
- Prevent access to subscription dialog when no event types are available (eventTypes={[]})
- Hide the "Subscribed to:" chip completely when there are zero event types to subscribe to (fixes failing test)
- Improve SubscriptionInfo chip rendering: only show when there is meaningful subscription info
- Add "Subscribe to All", "Unsubscribe from All", and "Reset to Default" buttons in subscription dialog
- Display per-event-type received count in subscription dialog
- Add proper disabled states for subscription buttons when no event types exist
- Fix logger EventSource creation to use the correct subscribed filters (not the full list)
- Ensure CONNECTION events are always shown even with objectName filtering
- Improve test coverage and fix failing test `handles subscription dialog with no eventTypes`
- Add comprehensive error handling and logging for subscription updates
- Refactor event filtering logic to clearly separate display filters from subscription filters
- Make subscription chip clickable to open management dialog, with settings icon to reset to default
- Add visual feedback when subscriptions are updated

This completes the full subscription UX overhaul: users can now safely manage event subscriptions without immediate side effects, and the component behaves correctly in all edge cases including zero available event types.
- Add comprehensive unit tests for the entire eventSourceManager module
- Cover all public functions: createEventSource, closeEventSource, getCurrentToken, updateEventSourceToken, configureEventSource, startEventReception
- Add full test suite for logger-specific functions: createLoggerEventSource, closeLoggerEventSource, updateLoggerEventSourceToken, configureLoggerEventSource, startLoggerReception
- Test all event handlers (NodeStatusUpdated, ObjectStatusUpdated, InstanceStatusUpdated, DaemonHeartbeatUpdated, ObjectDeleted, InstanceMonitorUpdated, InstanceConfigUpdated, etc.)
- Verify buffer management, flushing, and edge cases (unchanged data, missing fields, invalid JSON)
- Test reconnection logic, exponential backoff, max attempts, and authentication error handling (401 with silent renew and fallback)
- Cover token update flows, localStorage interaction, and EventSource lifecycle (open, close, cleanup)
- Test query string generation with valid/invalid filters and objectName-specific filtering
- Add tests for navigationService redirect
- Verify logger-specific behaviors: selective event listener attachment, connection logging, error logging, and reconnection logging based on subscribed filters
- Ensure proper mocking of EventSourcePolyfill, useEventStore, useEventLogStore, console, localStorage, and window.oidcUserManager
- Add detailed assertions for console logs, store updates, and EventSource calls
- Implement global dark mode context with localStorage persistence
- Add dark mode toggle button in NavBar with dynamic icon (moon/sun)
- Add secondary dark mode toggle button in WhoAmI page for user convenience
- Create comprehensive dark theme with CSS custom properties for consistent theming
- Implement dynamic Material-UI theme switching using ThemeProvider
- Fix background color issues in WhoAmI page sections (Permission Details, Server Info)
- Ensure colored status indicators (green, red, orange, grey) remain visible in both modes
- Preserve colored icons while adapting text and background colors
- Apply dark mode to all MUI components including tables, cards, inputs, and chips
- Maintain NavBar color consistency across both themes
- Add smooth transitions for theme switching
- Handle theme persistence across page reloads

Key features:
- Toggle dark mode from both NavBar and WhoAmI page
- All colored status indicators maintain their semantic colors in both modes
- Complete dark theme coverage for all UI components
- Proper contrast and readability in dark mode
- Backward compatibility with existing light theme

The implementation provides a seamless dark mode experience while maintaining all existing functionality and visual cues.
Components modified:
- Namespaces: Removed "Namespaces" title
- Network: Removed "Network" title
- Heartbeats: Removed "Heartbeats" title
- NodesTable: Removed "Node Status" title
- Objects: Removed "Objects" title
- Pools: Removed "Pools" title
- WhoAmI: Removed "WhoAmI" title

Test updates:
- Objects.test.js: Updated all tests to check for elements that are
  always present instead of the removed titles. Modified
  waitForComponentToLoad to verify the 'Namespace' filter input.
- Heartbeats.test.js: Updated tests to verify table structure and
  header presence instead of the title. Modified 'renders basic
  structure' and 'handles edge case with empty streams array' tests.
- Namespaces.test.js: Updated tests to check for table headers and
  structure instead of the removed title. Modified 'renders title and
  table structure' to 'renders table structure' and updated
  'handles malformed objectStatus data'.

All tests have been updated to maintain comprehensive coverage while
adapting to the new UI structure. The changes ensure:
- Tests no longer fail due to missing title elements
- Tests verify actual functionality and UI components that remain
- Test assertions focus on stable, always-present elements
- Accessibility is maintained through proper ARIA labels and structure

The UI now provides a cleaner, more streamlined experience while
maintaining full functionality and comprehensive test coverage.
- Removed CONNECTION_OPENED, CONNECTION_ERROR, RECONNECTION_ATTEMPT, and MAX_RECONNECTIONS_REACHED
  event logging from createLoggerEventSource as they were not being used
- Updated tests to reflect new behavior where connection lifecycle events are no longer logged
- Maintained all core SSE functionality for system events (NodeStatusUpdated, ObjectStatusUpdated, etc.)
- Preserved reconnection logic and authentication handling without connection event logging
- Simplified logger event source to only process subscribed system events
- Implement search term highlighting in JSON data display using HTML span elements
  with custom CSS classes for colored syntax and search term highlighting
- Modify event type display to use standard MUI Chip components with border
  indication for search matches, ensuring text remains in single DOM node
- Add `escapeHtml` utility function to safely escape HTML characters in displayed content
- Create `syntaxHighlightJSON` function to apply both syntax coloring and search highlighting
  to JSON data in collapsed and expanded views
- Update `JSONView` component to accept `searchTerm` prop and apply highlighting
- Maintain existing filtering functionality while adding visual feedback for matches
- Preserve all existing test functionality by avoiding DOM node fragmentation in event types
- Ensure backward compatibility with existing event log filtering and display features

Key changes:
- Search terms are now highlighted with yellow background in both JSON data and event type chips
- Event type chips show yellow border when matching search term for visual indication
- JSON syntax highlighting preserved (keys, strings, numbers, booleans, null values)
- All existing tests pass, including the "filters logs by search term" test
- No breaking changes to existing API or component behavior

The solution balances visual feedback with testability by:
1. Using CSS-based highlighting in JSON (where complex HTML is acceptable)
2. Using border indication for event types (keeping text in single DOM node)
3. Maintaining all existing filtering and display logic

Test coverage: All existing tests pass including complex filtering scenarios and edge cases.
- Add CONNECTION_EVENTS constant to define unwanted connection event types
  (CONNECTION_OPENED, CONNECTION_ERROR, RECONNECTION_ATTEMPT,
   MAX_RECONNECTIONS_REACHED, CONNECTION_CLOSED)

- Introduce filteredEventTypes useMemo to automatically exclude connection
  events from available event types

- Update baseFilteredLogs to filter out connection events from display

- Modify SubscriptionDialog to use filteredEventTypes instead of raw eventTypes
  for event selection and "Subscribe to All" functionality

- Update SubscriptionInfo component to reference filteredEventTypes

Connection events are now completely hidden from users and cannot be
subscribed to, while remaining available for internal application use.
- Added debounced search functionality to improve performance and user experience
- Created separate state for immediate search input (searchTerm) and debounced term (debouncedSearchTerm)
- Implemented useEffect with 300ms debounce timeout using useRef for cleanup
- Updated filteredLogs memo to depend on debouncedSearchTerm instead of searchTerm
- Modified JSONView and EventTypeChip components to use debouncedSearchTerm for highlighting
- Added clear button to search field for better UX
- Updated handleClear and handleClearFilters to reset both search states
- Adjusted filter indicator to show debouncedSearchTerm status
- Maintained all existing functionality while adding async search behavior

Benefits:
- Reduces unnecessary re-renders during rapid typing
- Improves performance with large log datasets
- Provides smoother user experience with delayed filtering
- Eliminates lag while typing in search field
- Preserves all existing features and styling
Major improvements to the EventLogger component:

- Added ALL_EVENT_TYPES constant with comprehensive list of available event types
- Implemented localStorage persistence for manual subscriptions using custom usePersistedState hook
- Enhanced subscription dialog with ability to add/remove custom event types
- Separated subscriptions into "Page Events" (from props) and "Additional Events" (manually added)
- Added UI indicators showing count of manual subscriptions
- Improved subscription dialog UI with better organization and visual separation
- Enhanced subscription filtering logic to respect both page events and manual subscriptions
- Added proper cleanup of manual subscriptions when they become part of page events
- Improved subscription info display with additional chip showing manual subscription count
- Enhanced subscription dialog with "Add Additional Event Type" dropdown and clear buttons
- Updated event source management to only start when subscriptions exist
- Added error handling for localStorage operations
- Fixed subscription logic to include connection events from page props
- Improved visual hierarchy in subscription dialog with distinct sections
Major improvements to the EventLogger component:

- Added ALL_EVENT_TYPES constant with comprehensive list of available event types
- Implemented localStorage persistence for manual subscriptions using custom usePersistedState hook
- Enhanced subscription dialog with ability to add/remove custom event types
- Separated subscriptions into "Page Events" (from props) and "Additional Events" (manually added)
- Added UI indicators showing count of manual subscriptions
- Improved subscription dialog UI with better organization and visual separation
- Enhanced subscription filtering logic to respect both page events and manual subscriptions
- Added proper cleanup of manual subscriptions when they become part of page events
- Improved subscription info display with additional chip showing manual subscription count
- Enhanced subscription dialog with "Add Additional Event Type" dropdown and clear buttons
- Updated event source management to only start when subscriptions exist
- Added error handling for localStorage operations
- Fixed subscription logic to include connection events from page props
- Improved visual hierarchy in subscription dialog with distinct sections
- Fixed `syntaxHighlightJSON` function to properly highlight search terms inside JSON strings between quotes
- Changed highlighting approach: first apply search highlights on escaped JSON, then apply syntax coloring
- Ensured search terms are properly escaped to match within HTML-escaped JSON content
- Added check to prevent double-wrapping of already highlighted text with syntax coloring spans
- Improved regex escaping for search terms to handle special characters correctly

The search functionality now correctly highlights matching text within JSON string values, not just keys and other JSON tokens.
- Added touch event handling for mobile drawer resizing (touchstart, touchmove, touchend)
- Fixed failing test "clears resize timeout on mouseUp during resize" with proper timeout cleanup
- Fixed failing test "applyHighlightToMatch - branch when index === -1" with improved test patterns
- Added visual resize indicator and improved mobile UX
- Set search debounce to 0ms in test environment for immediate execution
- Added responsive design for mobile devices
- Enhanced event listener management and timeout cleanup
- All existing functionality preserved
…ence and UI enhancements

- Add per-page persistence of subscriptions using a unique pageKey based on objectName and filtered event types
- Default subscriptions now include all page-specific event types automatically
- Refactor SubscriptionDialog:
  - Simplify buttons: 'Subscribe to All', 'Subscribe to Page Events', 'Unsubscribe from All'
  - Remove redundant 'Clear All' button
  - Remove custom event type input (unused)
  - Remove page/additional chips in list for cleaner UI
  - Apply button now directly sets full subscription list and clears logs on change
- Update SubscriptionInfo component:
  - Show total subscribed count and object name if applicable
  - Display all subscribed types as deletable chips with count
  - Settings icon opens dialog
- Optimize event source management:
  - startLoggerReception now called with exact required events (including connection events)
  - Close source only when no events to subscribe to
  - No cleanup closure on unmount (shared connection managed globally)
- Improve filtering logic for baseFilteredLogs to handle no subscriptions case correctly
- Minor UI cleanups and style adjustments in dialog

This ensures subscriptions are isolated per page/object, more intuitive to manage, and logs are cleared when changing subscriptions to avoid confusion.
Problem:
- EventLogger was persisting manual subscriptions across page navigation using localStorage
- When returning to a page, it would show the last manually selected subscriptions instead of the page's default events
- This caused confusion as users expected to see events relevant to the current page

Solution:
- Removed localStorage persistence for manual subscriptions
- Changed manualSubscriptions to useState initialized with filteredEventTypes
- Added initialization logic to reset subscriptions to page events on component mount
- Ensures each page shows its relevant events by default when visited

Key changes:
1. Removed usePersistedState hook that was saving to localStorage
2. Changed to regular useState initialized with current page's filteredEventTypes
3. Added useEffect with useRef to initialize subscriptions only once on mount
4. This prevents infinite re-render loops while maintaining correct initialization

Impact:
- Users now see page-relevant events by default when navigating between pages
- Manual subscription changes are still possible but only persist for the current session
- No more confusion about which events are being monitored on each page
Add comprehensive test for SubscriptionDialog component to verify:
- Opening subscription dialog via settings button
- "Subscribe to All" button interaction
- "Unsubscribe from All" button interaction
- "Subscribe to Page Events" button interaction
- Individual checkbox toggling functionality
- Apply Subscriptions button functionality and dialog closure

This test ensures all SubscriptionDialog UI interactions work correctly
and the component behaves as expected when managing event subscriptions.
- Implement clickable table headers for sorting columns similar to Heartbeats page
- Add sorting icons (KeyboardArrowUpIcon, KeyboardArrowDownIcon) to indicate sort direction
- Enable sorting by:
  - Status column (global object status)
  - Object column (object name)
  - Node columns (individual node statuses)
- Add handleSort function to toggle sort direction or switch sort columns
- Update TableHead cells to be clickable with visual feedback
- Maintain existing sorting logic in sortedObjectNames useMemo
- Enhance UX with cursor pointer and sorting indicators
… and Objects components

Changes made to NodesTable.jsx:
- Reorganized the actions button container to use the same structure as Objects.jsx
- Positioned the "Actions on selected nodes" button at the top-right corner
- Applied `justifyContent: "space-between"` for consistent alignment
- Added `position: "sticky"`, `top: 0`, and `zIndex: 10` to keep the button visible during scrolling
- Created an empty left section (`<Box sx={{ flexGrow: 1 }}></Box>`) to maintain structural consistency with Objects component
- Moved the actions Menu inside the same container for better organization

Result:
- Both components now have their "Actions on selected" buttons positioned consistently at the top-right
- Improved UI consistency across different views of the application
- Maintains the same user experience pattern for performing actions on selected items
- Add new columns "Booted At" and "Updated At" to the nodes table
- Implement sorting functionality for both new date columns
- Add conditional tooltip for booted_at (only shows on hover when date exists)
- Always show tooltip for updated_at with fallback to "-" for empty dates
- Improve table content centering with align="center" on all TableCells
- Increase table minWidth from 900 to 1100 to accommodate new columns
- Add date formatting utility with relative time display (e.g., "2h ago", "3d ago")
- Replace "Never" with "-" for empty/null dates
- Clean up tooltips and improve visual consistency
- Add comprehensive tests for the formatDate utility function
- Add tests for new booted_at and updated_at columns rendering
- Test conditional tooltip behavior for booted_at column
- Add tests for onOpenLogs callback functionality
- Improve test coverage for edge cases and error handling
- Add mocks for additional MUI icons used in the component
- Test zoom level calculation and Safari browser detection
- Test menu filtering logic based on node frozen state
- Add tests for scroll position handling in calculateMenuPosition
- Test missing window scroll properties edge case
- Improve time handling with jest.setSystemTime for consistent date tests
Added comprehensive test cases to improve test coverage and robustness of the NodesTable component:

- Extended sorting tests for all table columns including booted_at, updated_at, and version with edge cases
- Added action handling tests for menu interactions and state management
- Implemented touch event tests for drawer resizing functionality
- Added tests for dialog confirmation scenarios and error handling
- Enhanced test cases for sorting logic, including missing data handling
- Added Safari-specific browser compatibility tests for menu positioning
- Included tests for log drawer functionality and state cleanup

The added tests cover:
- handleAction function for both single node and batch operations
- Menu positioning calculations and browser-specific handling
- Touch event handling for responsive drawer resizing
- Edge cases in sorting logic with missing nodeStats and nodeMonitor data
- Dialog state management and cleanup
- Error scenarios and user interaction flows

This ensures better reliability and maintainability of the NodesTable component.
- Changed main containers to use height: 100vh instead of minHeight
- Implemented flexbox layouts with flex: 1 for proper space distribution
- Replaced fixed maxHeight with flex: 1 and minHeight: 0 for TableContainers
- Added overflow handling for proper internal scrolling
- Maintained sticky headers and filter functionalit
- Change minHeight to height: "100vh" in main containers to prevent content overflow
- Add flexDirection: "column" and overflow: "hidden" for proper layout structure
- Modify TableContainer to use flex: 1 and minHeight: 0 for internal scrolling
- Add window.scrollTo(0, 0) on component mount to ensure starting at top of page
- Add flexShrink: 0 to non-scrollable elements (titles, alerts, filters)
- Add useRef to container for direct scroll control
- Apply consistent layout pattern across Network and NetworkDetails pages
- Change main container from minHeight to height: "100vh" for consistent sizing
- Add flexDirection: "column" and overflow: "hidden" for proper layout structure
- Implement flexbox layout with flex: 1 for content container
- Modify TableContainer to use flex: 1 and minHeight: 0 for internal scrolling
- Remove Paper component from TableContainer to simplify layout
- Ensure content fills available height with proper overflow management
- Fixed Objects component:
  - Changed filter container position from top: 64 to top: 0
  - Increased table header z-index from 3 to 20 to appear above filters
  - Added padding-left to header cells for better alignment
  - Added position: relative to TableContainer for proper positioning
  - Maintained flex layout with flex: 1 and minHeight: 0 for scrollable table

- Fixed Heartbeats component:
  - Changed filter container position from top: 64 to top: 0
  - Increased table header z-index from 1 to 30 (above filters' z-index: 20)
  - Added padding-left and padding-right to header cells
  - Added position: relative to TableContainer and Table
  - Added consistent fontSize: small to sort icons

- Common improvements:
  - Ensured sticky headers remain visible above filter panels
  - Maintained responsive layout with proper overflow handling
  - Fixed z-index stacking context issues between filter controls and table headers
Replace all direct console.* calls with logger utility for:
- Default function warnings (warn level)
- Error messages (error level)
- Debug/info messages (info level)

Changes:
- Import logger from '../utils/logger.js'
- Replace console.warn with logger.warn in default function props
- Replace console.error with logger.error for validation errors
- Replace console.log with logger.info for state change tracking
- Update getResourceType function to use logger consistently

Benefits:
- Centralized logging control
- Consistent log levels across application
- Better debugging with structured logging
- Preparation for production logging configuration

Note: All existing functionality remains unchanged, only logging mechanism is updated
- Move auth resume handling from App to OidcInitializer for better OIDC integration
- Add silent renew attempt for OIDC tokens when app resumes with expired token
- Change useRefreshToken from false to true in oidcConfiguration to enable refresh token usage
- Update OidcInitializer to handle token expiration on resume by attempting silent renew
- Keep non-OIDC auth resume logic unchanged in OidcInitializer
- Remove duplicate auth resume handling from App component
- Update tests to reflect useRefreshToken: true change in oidcConfiguration
Summary
- Upgrade from Node.js 18 to Node.js 22.14.0 (Active LTS until 2027)
- Update all dependencies for compatibility and security
- Fix tests to accommodate new UI components

Changes
- Node.js: v22.14.0 LTS with engine requirements in package.json
- Dependencies: Updated React, TypeScript, ESLint, testing libraries
- Removed: Unused dependencies (`next`, `util`, legacy `oidc-client`)
- Tests: Fixed assertions for multiple element occurrences from EventLogger
- Config: Added `.nvmrc` and Volta configuration

Migration

nvm install 22.14.0
nvm use
rm -rf node_modules package-lock.json
npm install
- Remove test.yml workflow duplicated by Node.js CI
- Remove continue-on-error from release build tests
- Ensure releases fail if tests do not pass
Major refactoring of test files to enhance test reliability and prevent React warnings:

EventLogger.test.js:
- Wrap all state-changing operations in act() calls to prevent React warnings
- Add proper timer management with jest.useFakeTimers() and jest.useRealTimers()
- Implement console.error spy to suppress specific React warnings about unique keys
- Ensure consistent cleanup in afterEach with proper mock restoration
- Add proper async/await patterns for all waitFor operations
- Fix mock implementations to return consistent data structures
- Improve timer handling for debounce functionality in search tests
- Ensure proper cleanup of event listeners and timeouts
- Fix scroll event handling and mock implementations

LogsViewer.test.js:
- Add console.error suppression to prevent error logs during tests
- Wrap all render calls and state-changing operations in act()
- Mock logger utility to prevent console.error calls
- Improve async/await patterns for all async operations
- Ensure proper cleanup of timers and mocks
- Fix event handling to prevent React warnings

Namespaces.test.js:
- Improve mock implementations for Material-UI components
- Add proper cleanup of event sources
- Fix async operations and state updates
- Ensure proper navigation mocking
- Handle edge cases in filtering and sorting

NodesTable.test.js:
- Wrap all state-changing operations in act()
- Add console.error mocking for expected error cases
- Improve timer management for fake timers
- Fix async operations and event handling
- Ensure proper cleanup of localStorage and mocks
- Handle edge cases in sorting, filtering, and actions

ObjectDetails.test.js:
- Add console.error suppression to prevent React warnings about unique keys and descendant nesting
- Improve Material-UI component mocking to include all necessary props
- Enhanced mock implementations for better test isolation
- Add proper cleanup of event listeners and timeouts
- Improve async/await patterns for all waitFor operations
- Add missing props to mocked components (expandIcon, slotProps, etc.)
- Enhanced mock for LogsViewer component
- Improve event handling to prevent React warnings

Objects.test.js:
- Add comprehensive console.error suppression to ignore expected React warnings
- Enhanced mock implementations for better state management
- Add proper error handling for failed action execution tests
- Improve cleanup in afterEach with proper mock restoration
- Enhanced Material-UI component mocking
- Add proper console.error mocking for specific test cases
- Improve async operations and state updates
- Ensure consistent test execution without React warnings

The changes ensure that all tests run without React warnings, provide more reliable test execution, and improve test isolation across all components.
- Add setup in setupTests to mock console.error and console.warn during test execution
- Prevent cluttering test output with React warnings and other non-critical console messages
- Restore original console methods after all tests complete
@cgalibern cgalibern merged commit 4bdf104 into opensvc:main Jan 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants