Skip to content

LNK-4673: update admin UI to angular21 - #1384

Merged
arianamihailescu merged 9 commits into
devfrom
LNK-4673-UpdateAdminUITOAngular21
Jan 26, 2026
Merged

LNK-4673: update admin UI to angular21#1384
arianamihailescu merged 9 commits into
devfrom
LNK-4673-UpdateAdminUITOAngular21

Conversation

@arianamihailescu

@arianamihailescu arianamihailescu commented Jan 22, 2026

Copy link
Copy Markdown
Contributor

🛠️ Description of Changes

Upgrade to Angular 21

🧪 Testing Performed

Tested locally

🧑‍🔬 Unit Testing

  • I have written or updated unit tests to cover my changes

📓 Documentation Updated

Please update any relevant sections in the project documentation that were impacted by the changes in the PR.

Summary by CodeRabbit

Release Notes

  • Chores
    • Updated Angular framework dependencies from version 20 to 21
    • Updated Font Awesome integration from version 3 to 4

✏️ Tip: You can customize this high-level summary in your review settings.

@arianamihailescu
arianamihailescu requested a review from a team as a code owner January 22, 2026 21:54
@coderabbitai

coderabbitai Bot commented Jan 22, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

Updated Angular framework and dependencies from version 20.x to 21.x, including Angular Material and Font Awesome 4. Migrated template syntax across multiple components from structural directives (*ngIf, *ngFor) to Angular 21's control flow syntax (@if, @for). Removed CommonModule imports from standalone components and updated application bootstrap configuration with zone change detection provider.

Changes

Cohort / File(s) Summary
Angular Core Dependencies
Web/Admin.UI/package.json
Updated @angular/animations, @angular/cdk, @angular/common, @angular/compiler, @angular/core, @angular/forms, @angular/material, @angular/platform-browser, @angular/platform-browser-dynamic, @angular/router from 20.x to 21.x; updated dev dependencies @angular/build, @angular/cli, @angular/compiler-cli to 21.x; bumped @fortawesome/angular-fontawesome to v4.
Bootstrap Configuration
Web/Admin.UI/src/main.ts
Added provideZoneChangeDetection() import and integrated into bootstrap call with applicationProviders configuration; added error handling for bootstrap failure.
Link Navigation Bar Control Flow
Web/Admin.UI/src/app/components/core/link-nav-bar/link-nav-bar.component.html, link-nav-bar.component.ts
Migrated from *ngFor/*ngIf to @for/@if syntax; removed ng-container usage; cleaned up CommonModule and directive imports from component.
Kafka Dashboard Control Flow
Web/Admin.UI/src/app/components/kafka/kafka-dashboard/kafka-dashboard.component.html, kafka-dashboard.component.ts
Converted conditional rendering from *ngIf to @if blocks; removed CommonModule from imports.
Data Acquisition FHIR Query Config Form
Web/Admin.UI/src/app/components/data-acquisition/data-acquisition-fhir-query-config-form/data-acquisition-fhir-query-config-form.component.html, data-acquisition-fhir-query-config-form.component.ts
Major template restructuring: expanded authentication section with conditional fields (Auth Type, Key, Token URL, Audience, Client ID, User Name, Password); replaced min/max time inputs with explicit hour/minute/second selectors using @for loops; removed CommonModule and structural directive imports.
Reports Components Control Flow
Web/Admin.UI/src/app/components/reports/generate-report/generate-report-form.component.html, Web/Admin.UI/src/app/components/reports/reports-dashboard/reports-dashboard.component.html
Migrated from *ngIf/*ngFor to @if/@for syntax; restructured facility autocomplete and report type selection; reorganized date input handling and form mode radio group with corresponding conditional sections (file upload, manual patients, census).
Validation Config Components
Web/Admin.UI/src/app/components/validation-config/validation-categories/edit-validation-category/edit-validation-category.component.ts, validation-categories-list/validation-categories-list.component.ts
Removed CommonModule from standalone component imports.
Integration Test Control Flow
Web/Admin.UI/src/app/components/testing/integration-test/integration-test.component.html
Converted from *ngIf, *ngFor, and ng-template to @if, @for, and conditional blocks; restructured facility input, loading states, test toggle, data table rendering, error message panels, and event form sections.
Additional Component Cleanup
Web/Admin.UI/src/app/components/tenant/facility-view/view-report/view-report.component.html, Web/Admin.UI/src/app/components/sub-pre-qual-report/sub-pre-qual-report.component.ts, Web/Admin.UI/src/app/components/login/login.component.ts
Migrated view-report template from *ngIf with ng-template to @if/@else control flow; removed CommonModule imports from sub-pre-qual-report and login components.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • amphillipsLGC
  • dvargaslantana
  • nvmLantana

🐰 Hop along with Angular twenty-one,
Control flow syntax—refactoring's done!
@if, @for, the directives take flight,
CommonModule gone, templates feel light.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description follows the required template with all main sections completed: description of changes, testing performed, and unit testing checkbox.
Linked Issues check ✅ Passed The code changes comprehensively implement the LNK-4673 objective to upgrade AdminUI to Angular 21, including dependency updates and template syntax migrations.
Out of Scope Changes check ✅ Passed All changes are directly related to the Angular 21 upgrade objective: dependency updates, structural directive refactoring, and bootstrap configuration adjustments.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately summarizes the main objective of the pull request—upgrading the Admin UI to Angular 21. It is concise, clear, and directly reflects the primary change across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In
`@Web/Admin.UI/src/app/components/data-acquisition/data-acquisition-fhir-query-config-form/data-acquisition-fhir-query-config-form.component.html`:
- Around line 236-251: The password input currently shows plain text; update the
<input> element bound to formControlName "password" in the
DataAcquisitionFhirQueryConfigForm component so it uses a password mask by
adding type="password" (while preserving [readonly]="viewOnly",
formControlName="password", placeholder and existing clearPassword() behavior);
ensure the matSuffix clear button logic (related to passwordControl and
clearPassword()) and the mat-error condition using authTypeControl remain
unchanged so validation and read-only behavior continue to work.
- Around line 160-165: The mat-error blocks are shown whenever
authTypeControl.value != 'None' && authTypeControl.value != 'Basic' regardless
of the individual control's validity; update each error's *ngIf to require both
the authType condition AND that the specific control is invalid (and optionally
touched/dirty) so errors only show on actual validation failures. For example,
change the Auth Key mat-error to check authTypeControl.value != 'None' &&
authTypeControl.value != 'Basic' && authKeyControl.invalid &&
(authKeyControl.touched || authKeyControl.dirty), and apply the same pattern for
tokenUrlControl, audienceControl, clientIdControl, userNameControl and
passwordControl.

In
`@Web/Admin.UI/src/app/components/reports/generate-report/generate-report-form.component.html`:
- Around line 130-151: The table elements in the template are invalidly placed
inside a <div>; wrap the table structure properly by replacing the surrounding
<div class="input-container"> with a <table class="input-container"> (or add a
<table> inside the div) so the <thead>, <tr>, <th>, and <td> are children of a
<table>; keep the existing iteration and bindings (the `@if`(`@for`) blocks,
patients array usage and the removePatient(i) click handler) unchanged but
ensure the markup is a valid table parent for those elements.

In
`@Web/Admin.UI/src/app/components/reports/reports-dashboard/reports-dashboard.component.html`:
- Around line 106-114: The orphaned ng-template named `#noResultsFoundTemplate`
isn't rendered because the Angular 21 control-flow `@if` block using
reportListSummary closes without an `@else`; update the `@if` that checks
reportListSummary to include an `@else` branch that displays the
noResultsFoundTemplate (reference the existing template id
`#noResultsFoundTemplate`) so that when reportListSummary is empty/undefined the
fallback message is shown.

In
`@Web/Admin.UI/src/app/components/tenant/facility-view/view-report/view-report.component.html`:
- Around line 299-302: Remove the duplicated word in the loading message inside
the view-report component template: locate the span in
view-report.component.html that currently reads "Loading report summary
summary." and change it to "Loading report summary." so the loading state
displays a single correct phrase.
- Around line 1-29: The template adds two control-flow branches around
reportSummary and reportSummary.submitted; add tests to cover both branches: for
the Angular side, add/extend tests for ViewReportComponent to render with
reportSummary = null/undefined (assert nav links and action buttons are
absent/loader state) and with reportSummary present where submitted = false
(assert Acquisition Log button visible, Download button absent) and submitted =
true (assert both Acquisition Log and Download buttons present), using
fixture.componentInstance.reportSummary assignment, fixture.detectChanges(), and
query selectors for the buttons and links; for server/view-model logic covered
by XUnit, add tests that exercise the code paths which set the view model's
reportSummary and submitted flags (asserting the expected values emitted to the
view), so both loading vs content and submitted vs not-submitted branches are
covered.

In
`@Web/Admin.UI/src/app/components/testing/integration-test/integration-test.component.html`:
- Around line 104-126: The table headers render Trace ID and Error Message
conditionally when any error exists, but rows skip those <td> cells for items
without item.ErrorMessage, causing column misalignment; update the row rendering
in integration-test.component.html so that whenever the header condition
(presence of any error) is true you always emit the two <td> cells for TraceId
and ErrorMessage: for TraceId render either {{ item.TraceId }} or an empty cell
when item.ErrorMessage is falsy, and for ErrorMessage render the
<mat-expansion-panel> with content when item.ErrorMessage exists or render an
empty <td> (or a hidden/disabled panel) when it does not; keep the existing
bindings/isPanelOpen and togglePanel(CorrelationId) logic and the slice + length
checks only inside the panel content so structural alignment is preserved.
🧹 Nitpick comments (9)
Web/Admin.UI/src/app/components/reports/reports-dashboard/reports-dashboard.component.html (2)

37-37: Track by unique identifier for better change detection.

Tracking by object reference (track report) can cause unnecessary DOM re-renders when the list is refreshed from an API, as new object instances are created even if the data is unchanged. Since report.id is available and unique, use it for tracking.

♻️ Proposed fix
-            `@for` (report of reportListSummary; track report) {
+            `@for` (report of reportListSummary; track report.id) {

72-75: Consider using strict equality.

The conditions use loose equality (==) for boolean comparisons. While this works, strict equality (===) is preferred for clarity and to avoid unexpected type coercion.

♻️ Suggested change
              <span [ngClass]="{
-                    'status-pending': report.submitted == false,
-                    'status-submitted': report.submitted == true
+                    'status-pending': report.submitted === false,
+                    'status-submitted': report.submitted === true
                }">{{ report.submitted ? 'Submitted' : 'Pending' }}</span>
Web/Admin.UI/src/app/components/data-acquisition/data-acquisition-fhir-query-config-form/data-acquisition-fhir-query-config-form.component.html (1)

151-166: Consider consistent disabled/readonly usage.

The template mixes [disabled] (lines 12, 35, 61, etc.) and [readonly] (lines 154, 171, 188, etc.) for view-only mode. While both prevent editing:

  • disabled: Excludes the field from form submission and value
  • readonly: Field is still submitted and included in form value

If this is intentional (auth fields should be included in form value even in view-only mode), this is fine. Otherwise, consider using a consistent approach across all fields.

Web/Admin.UI/src/app/components/kafka/kafka-dashboard/kafka-dashboard.component.html (1)

3-12: Consider using @else for mutually exclusive conditions.

The current implementation works, but Angular 21's control flow supports @else for cleaner mutual exclusion:

♻️ Optional: Use `@else` syntax
-  `@if` (kafkaUrl) {
-    <p>
-      <a href="{{kafkaUrl}}" target="_blank">Kafka UI</a>
-    </p>
-  }
-  `@if` (!kafkaUrl) {
-    <p>
-      <span>Default Kafka UI is not available.</span>
-    </p>
-  }
+  `@if` (kafkaUrl) {
+    <p>
+      <a href="{{kafkaUrl}}" target="_blank">Kafka UI</a>
+    </p>
+  } `@else` {
+    <p>
+      <span>Default Kafka UI is not available.</span>
+    </p>
+  }
Web/Admin.UI/src/app/components/reports/generate-report/generate-report-form.component.html (1)

143-147: Redundant condition inside @for loop.

The @if (patients.length > 0) check is unnecessary here. If the patients array were empty, the @for loop wouldn't iterate and this code would never execute.

♻️ Remove redundant check
             <td class="header-cell">
-              `@if` (patients.length > 0) {
                 <button mat-icon-button color="warn" (click)="removePatient(i)">
                   <mat-icon>remove_circle</mat-icon>
                 </button>
-              }
             </td>
Web/Admin.UI/src/main.ts (1)

1-12: Correct Angular 21 bootstrap configuration.

Adding provideZoneChangeDetection() to applicationProviders is the recommended approach for configuring zone-based change detection in Angular 21.

Consider enabling eventCoalescing for potential performance improvements in change detection:

💡 Optional: Enable event coalescing for performance
-platformBrowserDynamic().bootstrapModule(AppModule, { applicationProviders: [provideZoneChangeDetection()], })
+platformBrowserDynamic().bootstrapModule(AppModule, { applicationProviders: [provideZoneChangeDetection({ eventCoalescing: true })], })

Event coalescing batches multiple change detection cycles triggered by rapid events into fewer cycles, which can improve performance.

Web/Admin.UI/src/app/components/testing/integration-test/integration-test.component.html (3)

28-32: Use stable tracking keys for @for loops to avoid DOM churn.

track fac, track entry, and track item rely on object identity. With async streams or rebuilt arrays, Angular will recreate DOM nodes and can reset expansion-panel state. Prefer stable identifiers (e.g., facilityId, topic, CorrelationId) if they’re unique.

♻️ Proposed change
-                `@for` (fac of filteredFacilities | async; track fac) {
+                `@for` (fac of filteredFacilities | async; track fac.facilityId) {
...
-                  `@for` (entry of displayedEntries; track entry) {
+                  `@for` (entry of displayedEntries; track entry[0]) {
...
-                      `@for` (item of entry[1]; track item; let i = $index) {
+                      `@for` (item of entry[1]; track item.CorrelationId; let i = $index) {

Also applies to: 89-92


80-85: Cache hasAnyError(displayedEntries) instead of recomputing in the template.

The method is invoked repeatedly (including inside loops). If it scans entries, this adds avoidable work each change detection. Consider precomputing a boolean in the component (e.g., hasDisplayedErrors) and binding to it.

💡 Example template update
-                    `@if` (hasAnyError(displayedEntries)) {
+                    `@if` (hasDisplayedErrors) {
...
-                        `@if` (hasAnyError(displayedEntries)) {
+                        `@if` (hasDisplayedErrors) {

Also applies to: 134-138


51-66: Add XUnit coverage for the new UI branches.

The new @if/@else branches (loading vs. button, and conditional forms) should have tests covering each branch (e.g., isLoading true/false, showReportScheduledForm/showPatientsAcquiredForm). Mock any external calls. As per coding guidelines.

Also applies to: 152-166

@arianamihailescu arianamihailescu changed the title LNK-4673 update admin UI to angular21 LNK-4673: update admin UI to angular21 Jan 22, 2026
@arianamihailescu
arianamihailescu merged commit 3c11a5c into dev Jan 26, 2026
17 checks passed
@arianamihailescu
arianamihailescu deleted the LNK-4673-UpdateAdminUITOAngular21 branch January 26, 2026 15:29
@coderabbitai coderabbitai Bot mentioned this pull request Jan 29, 2026
1 task
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