Commit Graph

19 Commits

Author SHA1 Message Date
Joseph Doherty
f3b33e7e1d fix(ui/treeview): union sessionStorage keys instead of overwriting
The previous fix tried to defer page-side RevealNode to the second
render so TreeView's async sessionStorage load could finish first. In
practice Blazor Server didn't always fire a second OnAfterRenderAsync
on the page after the deep-link load, so the reveal never ran.

Real fix: change TreeView's storage-load to UNION the restored keys
with whatever's already in _expandedKeys, instead of REPLACING. That
way the page can call RevealNode whenever it wants and the storage
restore can't clobber the reveal regardless of completion order. The
page-side guard simplifies back to a one-shot reveal on first render.

Semantic note: if a deep-link reveal expands an ancestor that the user
had previously collapsed, the deep link wins. Intentional — the URL
expresses the navigation intent.
2026-05-11 12:42:38 -04:00
Joseph Doherty
d8e6f44616 fix(ui/templates): defer deep-link reveal until TreeView restores sessionStorage
Both page.OnAfterRenderAsync(firstRender=true) and
TreeView.OnAfterRenderAsync(firstRender=true) ran concurrently:
- Page called RevealNode → added ancestor keys to _expandedKeys
- TreeView awaited treeviewStorage.load → replaced _expandedKeys with
  the persisted set (often empty if user collapsed before navigating)

Whichever JS interop completed second won. When TreeView won, the deep-link
reveal silently lost. Gate the reveal on firstRender==false so it runs
strictly after TreeView's restore is done.
2026-05-11 12:39:21 -04:00
Joseph Doherty
ca164dca03 fix(ui/templates): stop drop propagation on folder nodes
Without stopPropagation, dropping a template onto a folder fires both
OnDrop(folder) and OnDropOnRoot via event bubbling. The two async handlers
race on the same scoped DbContext, which is not thread-safe — the second
throws ObjectDisposedException and tears down the Blazor circuit. Surfaced
during browser smoke testing via JS-dispatched DragEvent sequence.
2026-05-11 12:28:05 -04:00
Joseph Doherty
acead212b2 fix(ui/templates): dereference string params with @ and stack toolbar below title
Smoke testing revealed two issues introduced by the modal extraction commit:

1. ErrorMessage / InitialName / TemplateName parameters on the dialog
   components were passed as bare strings (e.g. ErrorMessage="_newFolderError")
   instead of dereferenced C# expressions (ErrorMessage="@_newFolderError").
   Razor treats unquoted-but-not-@-prefixed values to string parameters as
   string literals — so the error block rendered the literal field name in
   red whenever the modal opened. Non-string parameters (int/IEnumerable)
   were fine since Razor treats those as C# expressions by default.

2. The Templates header + 4-button toolbar shared one flex row, but at
   col-md-4 / col-lg-3 width the buttons overflowed into the right-column
   empty-state area. Stack title above a full-width btn-group instead.
2026-05-11 12:20:40 -04:00
Joseph Doherty
3587ab4fcb refactor(ui/templates): extract dialog modals into shared components 2026-05-11 12:03:35 -04:00
Joseph Doherty
17e690f6ef test(ui/templates): cover drag-template-to-root via bUnit DragEventArgs 2026-05-11 12:00:07 -04:00
Joseph Doherty
ca3b34223d feat(ui/templates): reveal deep-linked template on initial render 2026-05-11 11:21:53 -04:00
Joseph Doherty
c60aad9df4 feat(ui/templates): native HTML5 drag-drop reorganization 2026-05-11 11:20:42 -04:00
Joseph Doherty
fc105acd7c feat(ui/templates): new-folder, new-template, move-template dialogs 2026-05-11 11:18:36 -04:00
Joseph Doherty
39e6e0a525 feat(ui/templates): per-kind context menus + folder rename/delete 2026-05-11 11:15:25 -04:00
Joseph Doherty
4977f99a74 feat(ui/templates): split-pane layout with folder + composition tree 2026-05-11 11:12:40 -04:00
Joseph Doherty
78165b3d99 feat(ui/templates): replace flat tree model with TmplNode discriminated by kind 2026-05-11 11:10:39 -04:00
Joseph Doherty
20f60c88f9 feat(ui/templates): load folders alongside templates 2026-05-11 11:09:16 -04:00
Joseph Doherty
a0a6bb4986 refactor(ui): replace manual template inheritance tree with TreeView component 2026-03-24 16:19:39 -04:00
Joseph Doherty
d3194e3634 feat: separate create/edit form pages, Playwright test infrastructure, /auth/token endpoint
Move all CRUD create/edit forms from inline on list pages to dedicated form pages
with back-button navigation and post-save redirect. Add Playwright Docker container
(browser server on port 3000) with 25 passing E2E tests covering login, navigation,
and site CRUD workflows. Add POST /auth/token endpoint for clean JWT retrieval.
2026-03-21 15:17:24 -04:00
Joseph Doherty
7740a3bcf9 feat: add JoeAppEngine OPC UA nodes, fix DCL auto-reconnect and quality push
- Add JoeAppEngine folder to OPC UA nodes.json (BTCS, AlarmCntsBySeverity, Scheduler/ScanTime)
- Fix DataConnectionActor: capture Self in PreStart for use from non-actor threads,
  preventing Self.Tell failure in Disconnected event handler
- Implement InstanceActor.HandleConnectionQualityChanged to mark attributes Bad on disconnect
- Fix LmxFakeProxy TagMapper to serialize arrays as JSON instead of "System.Int32[]"
- Allow DataType and DataSourceReference updates in TemplateService.UpdateAttributeAsync
- Update test_infra_opcua.md with JoeAppEngine documentation
2026-03-19 13:27:54 -04:00
Joseph Doherty
7dcdcc46c7 Replace hardcoded "system" user with actual logged-in user across all UI pages
All 22 occurrences of hardcoded "system" user string replaced with
GetCurrentUserAsync() which reads the Username claim from AuthenticationState.
Affected: Instances.razor (6), Sites.razor (2), Templates.razor (11),
SharedScripts.razor (3).
2026-03-17 14:09:04 -04:00
Joseph Doherty
3b2320bd35 Phases 4-6: Complete Central UI — Admin, Design, Deployment, and Operations pages
Phase 4 — Operator/Admin UI:
- Sites, DataConnections, Areas (hierarchical), API Keys (auto-generated) CRUD
- Health Dashboard (live refresh, per-site metrics from CentralHealthAggregator)
- Instance list with filtering/staleness/lifecycle actions
- Deployment status tracking with auto-refresh

Phase 5 — Authoring UI:
- Template authoring with inheritance tree, tabs (attrs/alarms/scripts/compositions)
- Lock indicators, on-demand validation, collision detection
- Shared scripts with syntax check
- External systems, DB connections, notification lists, Inbound API methods

Phase 6 — Deployment Operations UI:
- Staleness indicators, validation gating
- Debug view (instance selection, attribute/alarm live tables)
- Site event log viewer (filters, keyword search, keyset pagination)
- Parked message management, Audit log viewer with JSON state

Shared components: DataTable, ConfirmDialog, ToastNotification, LoadingSpinner, TimestampDisplay
623 tests pass, zero warnings. All Bootstrap 5, clean corporate design.
2026-03-16 21:47:37 -04:00
Joseph Doherty
d38356efdb Phase 1 WP-11–22: Host infrastructure, Blazor Server UI, and integration tests
Host infrastructure (WP-11–17):
- StartupValidator with 19 validation rules
- /health/ready endpoint with DB + Akka health checks
- Akka.NET bootstrap via AkkaHostedService (HOCON config, cluster, remoting, SBR)
- Serilog with SiteId/NodeHostname/NodeRole enrichment
- DeadLetterMonitorActor with count tracking
- CoordinatedShutdown wiring (no Environment.Exit)
- Windows Service support (UseWindowsService)

Central UI (WP-18–21):
- Blazor Server shell with Bootstrap 5, role-aware NavMenu
- Login/logout flow (LDAP auth → JWT → HTTP-only cookie)
- CookieAuthenticationStateProvider with idle timeout
- LDAP group mapping CRUD page (Admin role)
- Route guards with Authorize attributes per role
- SignalR reconnection overlay for failover

Integration tests (WP-22):
- Startup validation, auth flow, audit transactions, readiness gating
186 tests pass (1 skipped: LDAP integration), zero warnings.
2026-03-16 19:50:59 -04:00