Skip to content

Angular upgrade to v16#571

Merged
uldisrudzitis merged 3 commits intomasterfrom
enh-angular-upgrade-to-v16
Oct 2, 2025
Merged

Angular upgrade to v16#571
uldisrudzitis merged 3 commits intomasterfrom
enh-angular-upgrade-to-v16

Conversation

@uldisrudzitis
Copy link
Copy Markdown
Collaborator

@uldisrudzitis uldisrudzitis commented Oct 2, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Improved image cropping: more accurate initial crop, proper initialization sequencing, and smoother behavior.
    • Updated cropper-related styles to match the new cropper classes for consistent visuals.
  • Chores

    • Upgraded Angular, build tooling, and supporting libraries (framework, runtime, and toolchain) to major new versions.
    • Updated several UI/utility libraries and RxJS for compatibility.
  • Chore

    • Replaced tooltip library with a compatible alternative.
  • Refactor

    • Streamlined authentication guard declarations without changing runtime behavior.

@uldisrudzitis uldisrudzitis self-assigned this Oct 2, 2025
@uldisrudzitis uldisrudzitis added Enhancement dependencies Pull requests that update a dependency file labels Oct 2, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 2, 2025

Walkthrough

Upgrades Angular and related tooling to v16, replaces tooltip package, updates several UI libraries and rxjs/zone.js, adjusts AuthGuardService declaration, refactors image-cropper integration (adds imageLoaded/cropper-ready) and updates related module imports and SCSS selectors.

Changes

Cohort / File(s) Summary
Framework & dependencies
editor/package.json
Bumps Angular core/tooling to v16, updates Node engines, replaces ng2-tooltip-directive with @cloudfactorydk/ng2-tooltip-directive, upgrades rxjs, zone.js, NGXS plugins, and various UI/utility libraries.
Router guard declaration
editor/src/app/auth-guard.service.ts
Removes implements CanActivate, CanLoad from the class and consolidates Router imports; canActivate/canLoad logic unchanged.
Image cropper component & module
editor/src/app/sites/media/entry-gallery-image-editor.component.ts, editor/src/app/sites/media/site-media.module.ts
Adds imageLoaded(LoadedImage) and cropper-ready sequencing; binds crop events after image load; removes ImageCropperModule from module imports and moves the component to imports (declaration changes noted).
Shared module tooltip swap
editor/src/app/sites/shared/sites-shared.module.ts
Switches TooltipModule import source to @cloudfactorydk/ng2-tooltip-directive; exports unchanged.
Styles for image editor
editor/src/styles/_entry-gallery-image-editor.scss
Updates selectors from .source-image/.cropper to .ngx-ic-source-image/.ngx-ic-cropper to match ngx-image-cropper class names.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Editor as EntryGalleryImageEditorComponent
  participant Cropper as ImageCropperComponent

  User->>Editor: Select image
  Editor->>Cropper: load image/file
  Cropper-->>Editor: imageLoaded(LoadedImage)
  Note over Editor: capture dimensions\ninitialize crop bounds
  Editor->>Cropper: set crop bounds / wait for ready
  Cropper-->>Editor: cropperReady
  loop adjust/crop
    Cropper-->>Editor: imageCropped(event)
    Note over Editor: update preview / data
  end
  User->>Editor: Save
  Editor->>Server: persist cropped image
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I hopped through lines of package cheer,
Swapped tooltips and tuned the cropper near.
Pixels aligned with a whiskered grin,
Guards kept watch though the implements went thin.
A rabbit's nibble, build logs clear. 🐇✨

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 succinctly captures the primary change of upgrading the Angular framework to version 16, which is the core focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch enh-angular-upgrade-to-v16

📜 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 211f469 and 85e9d88.

⛔ Files ignored due to path filters (1)
  • editor/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • editor/package.json (1 hunks)

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

Caution

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

⚠️ Outside diff range comments (1)
editor/src/app/sites/media/entry-gallery-image-editor.component.ts (1)

217-246: Add null safety check for imageCroppedEvent.

The updateSize method accesses this.imageCroppedEvent properties without verifying it's defined. If this method is called before the first imageCropped event fires (e.g., via user interaction with width/height inputs), it will throw a runtime error.

Apply this diff to add null safety:

 updateSize(e) {
   let value = parseInt(e.value);

   if (isNaN(value) || value < 1) {
     value = 1;
   }

+  if (!this.imageCroppedEvent) {
+    return;
+  }
+
   if (e.field === 'width') {
     const x2 =
       this.imageCroppedEvent.cropperPosition.x1 +

Alternatively, disable the width/height inputs until after the first imageCropped event:

 <berta-setting
   *ngIf="cropperIsReady"
   [setting]="{
     slug: 'width',
     value: size.width
   }"
   [config]="{
     title: 'Width',
     format: 'text',
     enabledOnUpdate: true
   }"
   [error]="''"
-  [disabled]="false"
+  [disabled]="!imageCroppedEvent"
🧹 Nitpick comments (2)
editor/package.json (1)

35-35: Optional: bump RxJS to ^7.8.0
RxJS ^7.4.0 is the officially supported version for Angular 16; upgrading to ^7.8.0 adds bugfixes and minor enhancements with no breaking changes.

- "rxjs": "^7.4.0",
+ "rxjs": "^7.8.0",
editor/src/app/auth-guard.service.ts (1)

2-2: Restore guard interfaces & clean up unused canLoad

  • Restore CanActivate/CanLoad in imports and class declaration to preserve type safety and IDE support:

    -import { Router, ActivatedRouteSnapshot, Route } from '@angular/router';
    +import { Router, ActivatedRouteSnapshot, Route, CanActivate, CanLoad } from '@angular/router';-export class AuthGuardService {
    +export class AuthGuardService implements CanActivate, CanLoad {
  • All canLoad references in app-routing.module.ts are commented out; remove the canLoad() method and its Route import if it’s not used.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfd0a1d and 211f469.

⛔ Files ignored due to path filters (1)
  • editor/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • editor/package.json (1 hunks)
  • editor/src/app/auth-guard.service.ts (2 hunks)
  • editor/src/app/sites/media/entry-gallery-image-editor.component.ts (4 hunks)
  • editor/src/app/sites/media/site-media.module.ts (1 hunks)
  • editor/src/app/sites/shared/sites-shared.module.ts (1 hunks)
  • editor/src/styles/_entry-gallery-image-editor.scss (1 hunks)
🔇 Additional comments (7)
editor/package.json (3)

13-13: LGTM! Node engine constraint aligns with Angular 16.

The Node engine constraint correctly specifies Node 16.14+ or 18.x, which matches Angular 16's requirements.


17-25: LGTM! Angular 16.2.12 is a stable release.

The Angular packages are consistently upgraded to v16.2.12, which is a stable patch release with bug fixes and improvements over 16.0.0.


26-26: Manual verification required
Automated queries failed; please confirm Angular 16 compatibility and review security advisories for @cloudfactorydk/ng2-tooltip-directive@16.0.0, ng-sortgrid@16.0.0, ngx-color-picker@15.0.0, and ngx-image-cropper@8.1.1.

editor/src/styles/_entry-gallery-image-editor.scss (1)

22-28: LGTM! Class names updated to match ngx-image-cropper v8.x.

The selector updates from .source-image/.cropper to .ngx-ic-source-image/.ngx-ic-cropper correctly align with the ngx-image-cropper v8.x library's class naming conventions.

Based on learnings

editor/src/app/sites/media/site-media.module.ts (1)

17-17: LGTM! Correct usage of standalone component.

Moving EntryGalleryImageEditorComponent from declarations to imports is correct because the component is now marked as standalone: true (see line 28 in entry-gallery-image-editor.component.ts). Standalone components must be imported rather than declared in modules.

The removal of ImageCropperModule is also correct since the standalone component now imports ImageCropperComponent directly.

editor/src/app/sites/media/entry-gallery-image-editor.component.ts (2)

28-29: LGTM! Proper standalone component declaration.

The component is correctly declared as standalone with appropriate imports (ImageCropperComponent, NgIf, SitesSharedModule), which is the recommended pattern in Angular v16+.


114-116: Event binding order looks correct.

The template correctly binds events in the sequence: imageLoadedcropperReadyimageCropped. This ensures dimensions are captured before initializing the crop area.

Comment on lines +197 to +207
imageLoaded(image: LoadedImage) {
this.size = {
width: image.original.size.width,
height: image.original.size.height,
};
}

cropperReady() {
this.position = { x1: 0, y1: 0, x2: this.size.width, y2: this.size.height };
this.cropperIsReady = true;
}
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 | 🔴 Critical

🧩 Analysis chain

Verify event ordering guarantees from ngx-image-cropper.

The implementation assumes imageLoaded fires before cropperReady, so that this.size is initialized before being used in line 205. If cropperReady fires first, this.size would be undefined, causing position to be set with undefined values.

Verify that ngx-image-cropper guarantees this event ordering:

Consider adding a defensive check:

 cropperReady() {
+  if (!this.size) {
+    console.warn('cropperReady fired before imageLoaded');
+    return;
+  }
   this.position = { x1: 0, y1: 0, x2: this.size.width, y2: this.size.height };
   this.cropperIsReady = true;
 }

Based on learnings


🌐 Web query:

Does ngx-image-cropper v8.1.1 guarantee that the imageLoaded event fires before the cropperReady event?

💡 Result:

Short answer: No official guarantee in v8.1.1 — the README documents both events but does not promise a strict ordering. In practice imageLoaded is emitted when the image is loaded and cropperReady when the cropper has finished laying out and calculated dimensions, so imageLoaded typically fires before cropperReady, but that ordering is not documented as a guaranteed API contract. [1][2]

Sources:

  • ngx-image-cropper README (outputs: imageLoaded, cropperReady). [1]
  • Issues / docs that treat cropperReady as the signal to wait for before setting cropper position (shows intended usage but not an explicit ordering guarantee). [2]

References:
[1] ngx-image-cropper README (outputs list).
[2] GitHub issues / docs recommending waiting for cropperReady before manipulating the cropper.


Add guard in cropperReady to handle undefined size
ngx-image-cropper doesn’t guarantee imageLoaded fires before cropperReady; guard against missing this.size to avoid undefined values:

 cropperReady() {
+  if (!this.size) {
+    console.warn('cropperReady fired before imageLoaded');
+    return;
+  }
   this.position = { x1: 0, y1: 0, x2: this.size.width, y2: this.size.height };
   this.cropperIsReady = true;
 }
📝 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
imageLoaded(image: LoadedImage) {
this.size = {
width: image.original.size.width,
height: image.original.size.height,
};
}
cropperReady() {
this.position = { x1: 0, y1: 0, x2: this.size.width, y2: this.size.height };
this.cropperIsReady = true;
}
imageLoaded(image: LoadedImage) {
this.size = {
width: image.original.size.width,
height: image.original.size.height,
};
}
cropperReady() {
if (!this.size) {
console.warn('cropperReady fired before imageLoaded');
return;
}
this.position = { x1: 0, y1: 0, x2: this.size.width, y2: this.size.height };
this.cropperIsReady = true;
}
🤖 Prompt for AI Agents
In editor/src/app/sites/media/entry-gallery-image-editor.component.ts around
lines 197 to 207, cropperReady assumes this.size is defined and uses
this.size.width/height directly; add a guard to handle undefined this.size by
either returning early or falling back to safe defaults (e.g., width: 0, height:
0) before computing this.position, then set this.cropperIsReady only after
position is set; ensure no property access on undefined and preserve existing
behavior when size is available.

import { RouteButton } from '../../../app/inputs/route-button.component';
import { ActionButton } from 'src/app/inputs/action-button.component';
import { TooltipModule } from 'ng2-tooltip-directive';
import { TooltipModule } from '@cloudfactorydk/ng2-tooltip-directive';
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 | 🔴 Critical

🧩 Analysis chain

Verify the tooltip directive fork is actively maintained.

The original ng2-tooltip-directive is unmaintained, so switching to a fork is appropriate. However, multiple forks exist for Angular 16 compatibility (e.g., @amin-karimi/ng2-tooltip-directive, ng2-tooltip-directive-ngfix).

Ensure @cloudfactorydk/ng2-tooltip-directive is actively maintained and provides the required tooltip functionality.

Based on learnings

Run the following script to verify the package's maintenance status and recent releases:


🏁 Script executed:

#!/bin/bash
# Description: Check npm package metadata for @cloudfactorydk/ng2-tooltip-directive

# Check package metadata and recent versions
npm view @cloudfactorydk/ng2-tooltip-directive time versions --json | jq '{
  latest_version: .versions[-1],
  publish_dates: .time | to_entries | sort_by(.value) | reverse | .[0:5]
}'

# Check GitHub repository activity if available
npm view @cloudfactorydk/ng2-tooltip-directive repository --json | jq -r '.url' | sed 's/git+//;s/.git$//' | while read repo; do
  if [ -n "$repo" ]; then
    echo "Repository: $repo"
    gh api "repos/$(echo $repo | sed 's|https://github.com/||')" --jq '{
      stars: .stargazers_count,
      last_push: .pushed_at,
      open_issues: .open_issues_count
    }'
  fi
done

Length of output: 580


🏁 Script executed:

#!/bin/bash
# Retrieve the project's Angular core version
pkg=$(fd -e json package.json -d 2 | head -n1)
if [[ -z "$pkg" ]]; then
  echo "Error: package.json not found"
  exit 1
fi
echo "Using $pkg"
jq -r '.dependencies["@angular/core"] // .devDependencies["@angular/core"]' "$pkg"

Length of output: 32


🏁 Script executed:

#!/bin/bash
# Locate package.json files containing @angular/core and report their versions
files=$(rg -l '"@angular/core"' -g '*/package.json')
echo "Found package.json files:"
for f in $files; do
  version=$(jq -r '.dependencies["@angular/core"] // .devDependencies["@angular/core"] // "not found"' "$f")
  echo "$f -> @angular/core: $version"
done

Length of output: 72


🏁 Script executed:

#!/bin/bash
# Fetch peerDependencies of the tooltip directive package
npm view @cloudfactorydk/ng2-tooltip-directive peerDependencies --json

Length of output: 64


Align tooltip directive version with Angular ^16.2.12
@cloudfactorydk/ng2-tooltip-directive@18.0.0 requires Angular ^18.0.0, causing a peer-dependency mismatch with the project’s Angular ^16.2.12; pin to @cloudfactorydk/ng2-tooltip-directive@16.0.0 or upgrade Angular to v18.0.0.

🤖 Prompt for AI Agents
In editor/src/app/sites/shared/sites-shared.module.ts around line 25 the project
imports TooltipModule from @cloudfactorydk/ng2-tooltip-directive but the
installed package version 18.0.0 requires Angular ^18, causing a peer-dependency
mismatch with the repo's Angular ^16.2.12; update package.json to pin
@cloudfactorydk/ng2-tooltip-directive to 16.0.0 (or alternatively upgrade the
project Angular to v18.0.0), then run the package manager (npm/yarn/pnpm
install) to reinstall dependencies and verify the import still resolves and the
app builds.

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

Labels

dependencies Pull requests that update a dependency file Enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant