Skip to content

Angular upgrade to v11#562

Merged
uldisrudzitis merged 11 commits intomasterfrom
enh-angular-upgrade-to-v11
Oct 1, 2025
Merged

Angular upgrade to v11#562
uldisrudzitis merged 11 commits intomasterfrom
enh-angular-upgrade-to-v11

Conversation

@uldisrudzitis
Copy link
Copy Markdown
Collaborator

@uldisrudzitis uldisrudzitis commented Sep 30, 2025

Summary by CodeRabbit

  • Chores

    • Upgraded Angular framework and CLI to v11.x; TypeScript to 4.1.x and zone.js to 0.11.x.
    • Refreshed build/tooling stack and updated testing tooling and related types.
  • Refactor

    • Adjusted routing configuration to use legacy relativeLinkResolution.
  • Bug Fixes

    • Improved media listing robustness: guarded against missing tags, refined tag-based filtering, and added lifecycle cleanup to unsubscribe on destroy to prevent leaks.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 30, 2025

Walkthrough

Upgrade Angular and related tooling from v10.x to v11.x in editor/package.json; add RouterModule.forRoot option { relativeLinkResolution: 'legacy'; and add OnDestroy-based unsubscription plus safer tag/entry filtering in SiteMediaComponent.

Changes

Cohort / File(s) Summary
Angular and tooling upgrades
editor/package.json
Bumps Angular framework packages and CLI/build tooling to v11.x; updates zone.js to ~0.11.8; upgrades TypeScript to ~4.1.x; refreshes test/dev dependencies (Jasmine, Karma, ts-node, types/node, codelyzer, etc.).
Router initialization tweak
editor/src/app/app-routing.module.ts
Adds RouterModule.forRoot option { relativeLinkResolution: 'legacy' } to routing initialization; route definitions unchanged.
Site media lifecycle & filtering
editor/src/app/sites/media/site-media.component.ts
Implements OnDestroy with destroy$ Subject and takeUntil usage; guards for missing/empty tags (sets sectionTags to null when absent); safer active-tag handling and entry filtering (checks e.tags and e.tags.slugs before indexing).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant AppModule
  participant RouterModule
  participant Router

  User->>AppModule: Bootstraps app
  AppModule->>RouterModule: forRoot(routes, { relativeLinkResolution: 'legacy' })
  note right of RouterModule #DDEBF7: legacy relativeLinkResolution configured
  RouterModule->>Router: Initialize router with config
  User->>Router: Navigate via routerLink / URL
  Router-->>User: Resolve navigation using legacy relative link rules
Loading
sequenceDiagram
  autonumber
  participant SiteMediaComponent
  participant DataSource
  participant UI

  SiteMediaComponent->>DataSource: Request entries and tags
  DataSource-->>SiteMediaComponent: Return entries, tags (maybe empty)
  alt tags exist
    SiteMediaComponent->>SiteMediaComponent: set sectionTags = find(tags)
  else tags missing/empty
    SiteMediaComponent->>SiteMediaComponent: set sectionTags = null
  end
  alt active tag selected
    SiteMediaComponent->>SiteMediaComponent: filter entries checking e.tags and e.tags.slugs safely
  else no active tag
    SiteMediaComponent->>SiteMediaComponent: include entries where e.tags.slugs absent/empty
  end
  SiteMediaComponent->>UI: Render filtered entries
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

Possibly related PRs

  • Angular upgrade #554: Updates editor/package.json Angular dependency versions (related dependency/version bump).

Poem

I nibble on packages, hop from ten to eleven,
I tidy routes and guard tags with zen.
I unsubscribe softly when my time is due,
I sort the entries, then hop off — adieu! 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Angular upgrade to v11” succinctly captures the primary intent and main change of this pull request, which is to upgrade the project’s Angular framework and related dependencies from version 10 to version 11 without extraneous detail or unrelated terms.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch enh-angular-upgrade-to-v11

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c35066 and e2c3397.

📒 Files selected for processing (1)
  • editor/src/app/sites/media/site-media.component.ts (7 hunks)
🔇 Additional comments (6)
editor/src/app/sites/media/site-media.component.ts (6)

1-1: LGTM! Correct imports for OnDestroy lifecycle pattern.

The additions of OnDestroy, Subject, and takeUntil are necessary to implement proper subscription cleanup.

Also applies to: 3-3, 5-5


85-85: LGTM! Proper OnDestroy lifecycle setup.

The class correctly implements OnDestroy and declares the destroy$ subject for subscription cleanup using the standard takeUntil pattern.

Also applies to: 102-102


130-135: LGTM! Safer tag access with null guards.

The explicit check tags && tags.length > 0 before calling find prevents potential errors when tags are undefined or empty.


150-150: LGTM! Proper subscription cleanup.

The takeUntil(this.destroy$) operator correctly guards the subscription, preventing memory leaks when the component is destroyed.


155-156: LGTM! Cleaner route parameter extraction.

Extracting sectionParam and tagParam upfront improves readability and makes the parameter handling more explicit.

Also applies to: 160-162


213-216: LGTM! Correct OnDestroy implementation.

The ngOnDestroy method properly signals completion via next() and cleans up the subject with complete(), following Angular best practices.


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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
editor/src/app/app-routing.module.ts (1)

94-99: Re-test and consider re-enabling canLoad for the lazy shop module.

Now that Angular is updated, please re-check the previous issue and, if resolved, restore canLoad alongside canActivate to prevent loading the module for unauthorized users.

Suggested change (after verification):

   path: 'shop',
   loadChildren: () => import('./shop/shop.module').then((m) => m.ShopModule),
-  /** Can load appears not to be working correctly. @todo: update Angular, see if it helps */
-  // canLoad: [AuthGuardService],
+  // TODO: verify after Angular 11 upgrade; re-enable if OK
+  canLoad: [AuthGuardService],
   canActivate: [AuthGuardService],

Please confirm with a local navigation test (unauthenticated -> direct /shop) that the module isn’t fetched.

editor/package.json (1)

14-15: Allow Node 14 LTS and drop end-of-life Node 10

Engines currently restrict to Node 10.x and 12.x; Angular 11 requires Node ≥ 10.13.0 and recommends using current/active or maintenance LTS (Node 12 or 14). Since Node 10.x is EOL, update your engines field:

-  "node": "^10.13.0 || ^12.11.1"
+  "node": "^12.11.1 || ^14.15.0"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc4cdb3 and bd7ff78.

⛔ Files ignored due to path filters (1)
  • editor/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • editor/package.json (3 hunks)
  • editor/src/app/app-routing.module.ts (1 hunks)
🔇 Additional comments (2)
editor/src/app/app-routing.module.ts (1)

111-111: Pinning Router relativeLinkResolution to 'legacy' to preserve behavior in v11 — LGTM.

Good call to avoid surprises from the default change in Angular 11. Consider tracking a follow-up to validate relative links and switch to 'corrected' later to align with current defaults.

Would you like me to open an issue to track verifying links and migrating to 'corrected'?

editor/package.json (1)

18-26: Angular 11 dependency alignment looks consistent — LGTM.

Framework packages are in the 11.2.x line with matching zone.js 0.11.x.

Also applies to: 39-39

Comment thread editor/package.json
Comment on lines +42 to +47
"@angular-builders/custom-webpack": "^11.1.1",
"@angular-devkit/build-angular": "~0.1102.19",
"@angular-devkit/core": "^11.2.19",
"@angular/cli": "~11.2.19",
"@angular/compiler-cli": "^11.2.14",
"@angular/language-service": "^11.2.14",
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.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Tooling matches Angular 11’s TS 4.1 line — looks good; sanity-check the test runner combo.

@angular/* devkit/cli/compiler-cli v11 with typescript ~4.1.6 is consistent. Karma 6 + Jasmine 3.8 should work, but please run the test suite to confirm compatibility with any custom reporters.

Also applies to: 50-50, 57-57, 59-59, 68-69


🏁 Script executed:

#!/bin/bash
# Quick checks: ensure karma config aligns with installed plugins
fd -a 'karma.conf.js' | xargs -I{} sh -c 'echo "--- {} ---"; rg -n "coverageIstanbulReporter|karma-coverage" {} -n -C2'
# Look for deprecated Istanbul reporter usage with Karma 6

Length of output: 507


Replace deprecated coverage reporter
karma-coverage-istanbul-reporter was deprecated in Angular 11—install karma-coverage, update src/karma.conf.js to require('karma-coverage') instead of 'karma-coverage-istanbul-reporter', rename the coverageIstanbulReporter block to coverageReporter (and adjust the reporters array to include 'coverage'), then rerun tests to confirm coverage reports generate correctly.

🤖 Prompt for AI Agents
In editor/package.json around lines 42 to 47, the project currently relies on
the deprecated karma-coverage-istanbul-reporter; replace it with karma-coverage
by installing that package, then open src/karma.conf.js and change the
require/import from 'karma-coverage-istanbul-reporter' to 'karma-coverage',
rename the configuration object coverageIstanbulReporter to coverageReporter and
adapt its options to the karma-coverage schema (output directory, reporters
types like html/text-summary), update the karma.conf.js reporters array to
include 'coverage' (and remove the istanbul reporter entry), and finally run the
test suite to verify coverage reports are generated correctly.

Comment thread editor/package.json Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
editor/src/app/sites/media/site-media.component.ts (2)

153-159: ParamMap accessed incorrectly — use paramMap.get(...).

data.paramMap['params']['section'] can throw at runtime. paramMap is a ParamMap; use its API.

-        this.activeNav = {
-          site: data.activeNav.site,
-          section:
-            data.paramMap['params']['section'] ||
-            (this.sectionsList[0] && this.sectionsList[0].section.name),
-          tag: data.paramMap['params']['tag'],
-        };
+        const sectionParam = data.paramMap.get('section');
+        const tagParam = data.paramMap.get('tag');
+        this.activeNav = {
+          site: data.activeNav.site,
+          section:
+            sectionParam ||
+            (this.sectionsList[0] && this.sectionsList[0].section.name),
+          tag: tagParam,
+        };

150-199: Memory leak: subscription not torn down.

The component subscribes in ngOnInit but never unsubscribes; route/store streams are hot and long‑lived.

- import { Observable } from 'rxjs';
+ import { Observable, Subject } from 'rxjs';
  import { combineLatest } from 'rxjs';
- import { map } from 'rxjs/operators';
+ import { map, takeUntil } from 'rxjs/operators';
@@
-export class SiteMediaComponent implements OnInit {
+export class SiteMediaComponent implements OnInit, OnDestroy {
@@
-  selectedTag: string | null;
+  selectedTag: any | null; // see typing note below
   showAllSections: boolean;
+  private destroy$ = new Subject<void>();
@@
-    ])
-      .pipe(
-        map(([sections, tags, activeNav, entries, paramMap, queryParams]) => {
+    ])
+      .pipe(
+        map(([sections, tags, activeNav, entries, paramMap, queryParams]) => {
           // ...
-        })
-      )
+        }),
+        takeUntil(this.destroy$)
+      )
       .subscribe((data) => {
         // ...
       });
   }
+
+  ngOnDestroy() {
+    this.destroy$.next();
+    this.destroy$.complete();
+  }

If you prefer, replace with AsyncPipe to avoid manual subscription entirely.

Also applies to: 1-5, 85-85, 99-103

♻️ Duplicate comments (1)
editor/package.json (1)

61-61: Migrate from deprecated Istanbul reporter to karma-coverage.

karma-coverage-istanbul-reporter is deprecated for Karma 6+/Angular 11. Replace with karma-coverage and update karma.conf.js (coverageIstanbulReportercoverageReporter, add 'coverage' to reporters).

#!/bin/bash
# 1) Update devDependency
# npm i -D karma-coverage && npm rm karma-coverage-istanbul-reporter
# 2) Guide edits in karma.conf.js
fd -a 'karma.conf.js' | xargs -I{} rg -n 'coverageIstanbulReporter|istanbul|reporters' -n -C3 {}
🧹 Nitpick comments (2)
editor/src/app/sites/media/site-media.component.ts (2)

129-135: Guard against missing/heterogeneous tag arrays before sorting.

Nice addition checking tags length. However, if sectionTags.tag is undefined or sometimes a single object (not an array), [...sectionTags.tag] will throw. Normalize before sorting.

-                return {
-                  section,
-                  tags: sectionTags
-                    ? [...sectionTags.tag].sort((a, b) => a.order - b.order)
-                    : [],
-                };
+                const rawTags = sectionTags?.tag ?? [];
+                const tagsForSection = Array.isArray(rawTags)
+                  ? rawTags
+                  : rawTags ? [rawTags] : [];
+                return {
+                  section,
+                  tags: tagsForSection
+                    .slice()
+                    .sort((a, b) => Number(a.order) - Number(b.order)),
+                };

Also applies to: 139-141


99-101: Tighten types: add entries to selectedSections, fix selectedTag type.

Template uses selectedSection.entries and selectedTag['@value'], but the TS types don’t reflect that.

-  selectedSections: { section: SiteSectionStateModel; tags: any }[];
-  selectedTag: string | null;
+  selectedSections: {
+    section: SiteSectionStateModel;
+    tags: any[];            // or a dedicated Tag type if available
+    entries: SectionEntry[];
+  }[];
+  selectedTag: any | null;  // or that Tag type (recommended)

If you have a Tag interface (e.g., from SectionTagsInterface), use it instead of any.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd7ff78 and 6c35066.

⛔ Files ignored due to path filters (1)
  • editor/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • editor/package.json (2 hunks)
  • editor/src/app/sites/media/site-media.component.ts (2 hunks)
🔇 Additional comments (1)
editor/package.json (1)

18-26: I couldn’t locate tsconfig*.json or angular.json in the repo root. Let’s search under the editor/ directory and inspect for fullTemplateTypeCheck and ivy settings:

#!/bin/bash
find editor -type f -name 'tsconfig*.json'
find editor -type f -name 'angular.json'
rg -n 'fullTemplateTypeCheck' -C2 editor/tsconfig*.json
rg -n 'ivy' -C2 editor/angular.json

This will confirm your strict template type checks and Ivy compiler options.

Comment on lines +175 to 181
? e.tags &&
e.tags.slugs &&
e.tags.slugs.indexOf(this.activeNav.tag) > -1
: this.showAllSections
? true
: !e.tags || e.tags.slugs.length === 0;
: !e.tags || (e.tags.slugs && e.tags.slugs.length === 0);
})
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.

⚠️ Potential issue | 🟠 Major

Filtering excludes entries with undefined slugs; likely unintended.

!e.tags || (e.tags.slugs && e.tags.slugs.length === 0) skips entries where e.tags exists but slugs is undefined. If “undefined slugs” should be treated as untagged, include that case.

-                    : !e.tags || (e.tags.slugs && e.tags.slugs.length === 0);
+                    : !e.tags || !e.tags.slugs || e.tags.slugs.length === 0;

Optionally simplify and modernize:

-                    ? e.tags &&
-                        e.tags.slugs &&
-                        e.tags.slugs.indexOf(this.activeNav.tag) > -1
+                    ? !!e.tags?.slugs?.includes(this.activeNav.tag)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
? e.tags &&
e.tags.slugs &&
e.tags.slugs.indexOf(this.activeNav.tag) > -1
: this.showAllSections
? true
: !e.tags || e.tags.slugs.length === 0;
: !e.tags || (e.tags.slugs && e.tags.slugs.length === 0);
})
? !!e.tags?.slugs?.includes(this.activeNav.tag)
: this.showAllSections
? true
: !e.tags || !e.tags.slugs || e.tags.slugs.length === 0;
})
🤖 Prompt for AI Agents
In editor/src/app/sites/media/site-media.component.ts around lines 175 to 181,
the current filter treats entries with e.tags present but e.tags.slugs ===
undefined as NOT untagged and therefore excludes them; change the condition so
undefined slugs are treated as untagged by checking for absence of slugs (e.g.
use e.tags == null || !e.tags.slugs || e.tags.slugs.length === 0) and, when
matching a tag, prefer a safe includes check
(e.tags?.slugs?.includes(this.activeNav.tag)) to avoid exceptions; update the
ternary accordingly so undefined slugs are handled as empty arrays/untagged.

@uldisrudzitis uldisrudzitis merged commit 5d533a8 into master Oct 1, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant