Files
jdescopingtool/openspec/changes/archive/2026-01-01-implement-blazor-ui/specs/web-ui/spec.md
T
Joseph Doherty 26ff8d9b4f Initial commit: JDE Scoping Tool migration project
Set up repository with legacy .NET Framework 4.8 source (OLD/),
new .NET 10 Blazor solution (NEW/), OpenSpec specifications,
documentation, and project configuration.
2026-01-02 07:43:29 -05:00

10 KiB

Web UI Specification Delta

Purpose

This document captures ADDED and MODIFIED requirements for the Blazor WebAssembly user interface specific to the .NET 10 migration. It supplements the base specification at openspec/specs/web-ui/spec.md.

ADDED Requirements

Requirement: Blazor WebAssembly Hosting Model

The system SHALL use Blazor WebAssembly (WASM) as the client-side hosting model.

Business Rules

  • The client application SHALL run entirely in the browser via WebAssembly
  • The application SHALL communicate with the server exclusively via HTTP APIs and SignalR
  • The application SHALL NOT use server-side Blazor (SignalR for DOM updates)
  • Initial load SHALL include the .NET runtime and application assemblies
  • Subsequent navigation SHALL NOT require page reloads

Scenario: Initial application load

  • WHEN a user navigates to the application URL
  • THEN the browser downloads the .NET WASM runtime
  • AND the Blazor application initializes in the browser
  • AND subsequent interactions do not trigger server-side rendering

Requirement: JWT Token Authentication

The system SHALL use JWT tokens for API authentication stored in browser localStorage.

Inputs

  • Login credentials (username, password)
  • LDAP authentication endpoint

Outputs

  • JWT token stored in localStorage
  • Claims extracted for AuthenticationState

Business Rules

  • Tokens SHALL be stored in browser localStorage via JS interop
  • Tokens SHALL be automatically attached to outgoing HTTP requests
  • Token expiration SHALL trigger re-authentication prompt
  • Logout SHALL remove token from localStorage and clear auth state

Scenario: Login stores JWT token

  • WHEN user submits valid credentials
  • THEN the API returns a JWT token
  • AND the token is stored in localStorage under key "authToken"
  • AND AuthStateProvider parses claims from the token
  • AND subsequent API requests include Authorization header

Scenario: Token expiration

  • WHEN a stored token has expired
  • AND the user attempts an API call
  • THEN the API returns 401 Unauthorized
  • AND the user is redirected to the login page

Requirement: Custom AuthenticationStateProvider

The system SHALL implement a custom AuthenticationStateProvider for JWT-based authentication state.

Business Rules

  • AuthStateProvider SHALL parse JWT claims without server round-trip
  • Claims SHALL include username, roles, and expiration
  • State changes SHALL notify Blazor components via NotifyAuthenticationStateChanged
  • Invalid/expired tokens SHALL result in anonymous state

Scenario: Parse claims from JWT

  • WHEN AuthStateProvider initializes with a stored token
  • THEN it parses the token payload (base64-decoded JSON)
  • AND extracts claims into ClaimsPrincipal
  • AND sets authentication type to "jwt"

Requirement: SignalR Auto-Reconnect

The system SHALL implement automatic reconnection for SignalR connections with exponential backoff.

Reconnection Schedule

Attempt Delay
1 0 seconds
2 2 seconds
3 5 seconds
4 10 seconds
5 30 seconds

Business Rules

  • SignalR client SHALL use WithAutomaticReconnect configuration
  • Reconnection attempts SHALL follow exponential backoff schedule
  • UI SHALL indicate connection state during reconnection
  • Events received during reconnection SHALL be delivered after reconnect

Scenario: Network interruption recovery

  • WHEN the SignalR connection is lost
  • THEN the client attempts reconnection per the backoff schedule
  • AND logs reconnection attempts to console
  • AND upon successful reconnection, resumes receiving events

Requirement: File Download via JS Interop

The system SHALL use JavaScript interop for triggering browser file downloads.

Business Rules

  • Excel result files SHALL be downloaded via JS interop function
  • Template files SHALL be downloaded via direct URL navigation
  • Downloaded files SHALL prompt browser save dialog
  • File names SHALL be specified by the server response headers

JavaScript Functions

Function Purpose
downloadFileFromStream Download file from DotNetStreamReference
downloadFileFromUrl Download file from URL with filename

Scenario: Download search results

  • WHEN user clicks Download Results button
  • THEN API request fetches file as stream
  • AND JS interop triggers browser download dialog
  • AND file is saved with name "Search_{id}_Results.xlsx"

Requirement: Radzen Component Library Integration

The system SHALL use Radzen Blazor (free tier) for UI components.

Service Registration

  • DialogService SHALL be registered for confirmation dialogs
  • NotificationService SHALL be registered for toast notifications
  • RadzenComponents SHALL be registered via AddRadzenComponents()

CSS and JavaScript

  • Radzen CSS SHALL be included in index.html
  • No additional Radzen JavaScript required for core components

Scenario: Register Radzen services

  • WHEN the application starts
  • THEN DialogService is available for injection
  • AND NotificationService is available for injection
  • AND Radzen component styles are applied

Requirement: Async-First Service Design

The system SHALL use async methods for all service operations.

Business Rules

  • All HTTP client calls SHALL use async methods (GetFromJsonAsync, PostAsJsonAsync)
  • All service interfaces SHALL return Task or Task
  • Cancellation tokens SHALL be accepted on all service methods
  • UI SHALL remain responsive during API calls

Scenario: Async API call with loading state

  • WHEN user triggers a data load operation
  • THEN loading indicator displays immediately
  • AND API call executes asynchronously
  • AND UI updates when data arrives
  • AND loading indicator hides

Requirement: ILogger Client-Side Logging

The system SHALL use Microsoft.Extensions.Logging for client-side logging.

Business Rules

  • All services SHALL accept ILogger via constructor injection
  • Log levels SHALL be configurable in Program.cs
  • Logs SHALL output to browser console in development
  • Error logs SHALL include exception details

Log Levels by Category

Category Minimum Level
Default Information
Microsoft.AspNetCore Warning
SignalR Debug (dev) / Information (prod)

Requirement: Same-Window Navigation

The system SHALL use same-window navigation for all internal links (no popups or new tabs).

Business Rules

  • All internal navigation SHALL use NavigationManager.NavigateTo
  • Search detail links SHALL NOT open new windows
  • Queue links SHALL NOT open new tabs
  • Only external links MAY open new tabs (if any exist)

Scenario: Navigate to search detail

  • WHEN user clicks View button on search grid row
  • THEN NavigationManager.NavigateTo("/search/{id}") is called
  • AND current window navigates to search detail
  • AND no new window or tab opens

MODIFIED Requirements

Requirement: Clear Data Confirmation

The system SHALL display confirmation dialogs before clearing filter data.

Inputs

  • User clicks Clear Data button on any filter panel

Outputs

  • Confirmation dialog with OK/Cancel buttons
  • Data cleared only if user confirms

Business Rules

  • DialogService.Confirm SHALL be used for confirmation dialogs
  • Dialog title SHALL be "Confirm Clear"
  • Dialog message SHALL be "Are you sure you want to clear all items?"
  • Cancel SHALL leave data unchanged

Scenario: Clear filter with confirmation

  • WHEN user clicks Clear Data button
  • THEN confirmation dialog appears
  • AND if user clicks OK, filter list is cleared
  • AND if user clicks Cancel, filter list is unchanged

Requirement: Operator Filter Display

The system SHALL display Operator filter entries with AddressNumber, UserID, and FullName properties.

Display Format

Column Property Width
Address Number AddressNumber 120px
User ID UserID 100px
Full Name FullName Auto

Business Rules

  • Autocomplete dropdown SHALL display all three properties
  • Format: "{AddressNumber} - {UserID} - {FullName}"
  • Grid SHALL display all three properties in separate columns

Scenario: Select operator from autocomplete

  • WHEN user types in operator autocomplete
  • THEN dropdown shows results with format "12345 - JSMITH - John Smith"
  • AND selecting adds entry with all three properties to grid

Requirement: Error Handling Without Custom Error Pages

The system SHALL use Blazor's built-in error handling instead of custom error pages.

Business Rules

  • ErrorBoundary component SHALL wrap page content in MainLayout
  • Unhandled exceptions SHALL display inline error message
  • Error recovery SHALL be automatic on next navigation
  • Development mode SHALL show exception details
  • Production mode SHALL show generic error message

Scenario: Unhandled exception in component

  • WHEN an unhandled exception occurs in a Blazor component
  • THEN ErrorBoundary catches the exception
  • AND error content displays instead of the faulted component
  • AND other components remain functional
  • AND navigating away recovers the error boundary

Migration Notes

Legacy Pattern New Pattern Status
Kendo UI Grid RadzenDataGrid ADDED
Kendo DatePicker RadzenDatePicker ADDED
Kendo ComboBox RadzenAutoComplete ADDED
jQuery AJAX HttpClient ADDED
Forms Authentication JWT with localStorage MODIFIED
SignalR (jQuery) SignalR (.NET client) ADDED
New window navigation Same-window navigation MODIFIED
Custom error pages ErrorBoundary MODIFIED
Clear without confirm Clear with DialogService.Confirm MODIFIED

Open Questions

None - all design decisions resolved per best practice recommendations.