Skip to content

Conversation

@Abhinegi2
Copy link
Member

@Abhinegi2 Abhinegi2 commented Nov 19, 2025

PR Checklist

Before you request a manual PR review from someone, please go through all of this list, check the points and mark them checked here.
This helps us reduce the number of review cycles and use the time of our core reviewers more effectively.

  • all automatic CI checks pass (🟢)
    • i.e. code formatting (ng lint) passes
    • i.e. unit tests (ng test) passes
    • in some cases unit test coverage can be difficult to achieve. If that or any other CI check fails, you can also leave a short comment here why this should be accepted anyway.
  • manually tested (all) required functionality described in the issue manually yourself on the final version of the code (developer)
  • reviewed the "Files changed" section of the PR briefly yourself to check for any unwanted changes
    • e.g. clean up debugging console.log statements, disabled tests, ...
    • please also avoid changes that are not directly related to the issue of the PR, even small code reformatings make the review process much more complex
  • 🚦 PR status is changed to "Ready for Review"
    • while you are still working on initial implementation, keep the PR in "Draft" status
    • once you are done with your initial work, change to "Ready for Review". This will trigger some additional automated checks and reviews.
    • (PR = "Ready for Review" does not immediately request a manual review yet, first complete the further checks below)
  • marked each code review comment as resolved OR commented on it with a question, if unsure
    • both implementing suggestions of automatic code review or discarding them as not applicable is okay
  • all checkboxes in this checklist are checked (to show the reviewer this really is ready)
  • 🚦 moved the issue related to this PR to Status "Functional Review" to request a personal review

⏪ if issues are commented from testing or code review, make changes. Please then re-check every item of the checklist here again.


Remaining TODOs:

  • unit tests

Summary by CodeRabbit

  • New Features

    • Added progress tracking for bulk operations with a live progress dialog showing real-time status.
  • Improvements

    • Bulk edit and archive flows now use batched saves for faster operations and clearer feedback.
    • Entity list updates are buffered during bulk operations to reduce reloads and visual flicker.

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

@Abhinegi2 Abhinegi2 self-assigned this Nov 19, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 19, 2025

📝 Walkthrough

Walkthrough

Adds coordinated bulk-edit support: a new BulkOperationStateService manages bulk lifecycle and progress dialog (now using Angular Signals). Several services and components switch to bulk save flows (saveAll), buffer updates during bulk operations, and present reactive progress messages.

Changes

Cohort / File(s) Summary
Progress Dialog Signal Conversion
src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts, src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html, src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
Dialog now receives message: Signal<string>; template calls message(); tests provide a signal("...") value.
Confirmation Dialog Service
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
showProgressDialog signature changed to accept Signal<string> instead of string.
Bulk Operation State Service (new)
src/app/core/entity/entity-actions/bulk-operation-state.service.ts
New service exposing start/update/complete APIs, tracks expected vs processed counts, updates a signal-based progress message, shows/closes progress dialog, and cleans up on destroy.
Entity Actions & Tests
src/app/core/entity/entity-actions/entity-actions.service.ts, src/app/core/entity/entity-actions/entity-actions.service.spec.ts
Injects BulkOperationStateService; switches multi-entity flows to saveAll() with start/complete bulk lifecycle; progress messages wrapped with signal(); tests updated to mock BulkOperationStateService and adjust expectations.
Entity Edit Service
src/app/core/entity/entity-actions/entity-edit.service.ts
Uses BulkOperationStateService around saveAll() calls, moves pending-state assignment into success path, and handles errors by completing bulk operation.
Entity List Component
src/app/core/entity-list/entity-list/entity-list.component.ts
Injects BulkOperationStateService; updates subscription to use UpdatedEntity<T> type; buffers per-entity updates during bulk operations and triggers reload/completion flow when buffered.
Duplicate Records & Admin Overview
src/app/core/entity-list/duplicate-records/duplicate-records.service.ts, src/app/core/admin/admin-overview/admin-overview.component.ts
Integrated bulk operation start/complete calls and switched progress dialog messages to signal() where applicable.
Tests Adjusted
src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts, src/app/core/entity/entity-actions/entity-actions.service.spec.ts
Provide signal-wrapped dialog data and mock BulkOperationStateService; adapt expectations for bulk save (saveAll) usage.
Manifest
package.json
(Unchanged content referenced in manifest section)

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant UI as Client/UI
    participant EntityActions as EntityActionsService
    participant BulkState as BulkOperationStateService
    participant ProgressDlg as ProgressDialog
    participant Backend

    User->>UI: Trigger bulk edit (n entities)
    UI->>EntityActions: requestBulkAction(entities)
    activate EntityActions

    EntityActions->>BulkState: startBulkOperation(n)
    activate BulkState
    BulkState->>ProgressDlg: showProgressDialog(signal(message))
    activate ProgressDlg

    EntityActions->>Backend: saveAll(entities)
    activate Backend

    loop per entity update (events)
        Backend-->>EntityActions: entitySavedEvent
        EntityActions->>BulkState: updateBulkOperationProgress(1, false)
        BulkState->>ProgressDlg: update message signal
    end

    Backend-->>EntityActions: saveAll complete
    deactivate Backend

    EntityActions->>BulkState: completeBulkOperation()
    BulkState->>ProgressDlg: close dialog
    deactivate ProgressDlg
    deactivate BulkState
    deactivate EntityActions

    ProgressDlg-->>UI: show completion
    UI-->>User: notify success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • sadaf895
  • sleidig

Poem

🐰 Hops of code, a flurry and fun,
Bulk edits bound, now done as one.
Signals hum softly, progress in view—
Many saved quick, a carrot for you! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive PR description follows the template structure with issue reference, completed checklist items, and status moved to Functional Review, but lacks any narrative explanation of changes made. Add a detailed summary of what was changed (e.g., new BulkOperationStateService, Signal wrapper changes, bulk save implementation) and why these changes address issue #2843's performance concerns.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: implementing bulk edit functionality to address the performance issue of slow one-by-one updates.
Linked Issues check ✅ Passed The code changes implement bulk write functionality via saveAll, add BulkOperationStateService for bulk operation tracking, and integrate progress dialog updates to meet all primary objectives from issue #2843.
Out of Scope Changes check ✅ Passed All code changes are directly related to bulk edit optimization: Signal-based message handling for progress dialogs, BulkOperationStateService implementation, and entity update buffering during bulk operations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

@github-actions
Copy link
Contributor

Deployed to https://pr-3451.aam-digital.net/

@argos-ci
Copy link

argos-ci bot commented Dec 29, 2025

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Jan 7, 2026, 5:50 PM

@Abhinegi2
Copy link
Member Author

@sleidig I created a separate service file and used requestAnimationFrame to detect when the table rendering is complete in the UI and seems to be working now.

Could you check the current bulk edit action functionality and also review the codebase so that If you have any feedback or suggestions, I can work on them

@Abhinegi2
Copy link
Member Author

todo:

  • Update a progress bar to show count, like 3 out of 20.

@sleidig sleidig requested a review from sadaf895 January 5, 2026 12:59
Copy link
Member

@sleidig sleidig left a comment

Choose a reason for hiding this comment

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

Works amazing 🥇 Great to see the progress and much faster than previously.
(I couldn't think of any edge case or way to trip the counter or anything yet ... if anyone has ideas how to break it, please go for it! 😅 )

Can we already integrate this (progress indicator) for bulk delete also here?

@Abhinegi2 Abhinegi2 marked this pull request as ready for review January 7, 2026 06:32
Copy link
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: 3

🤖 Fix all issues with AI agents
In @src/app/core/entity/entity-actions/bulk-operation-state.service.ts:
- Around line 91-98: Remove the debug console.log from updateProgressDialog:
delete the console.log(...) call inside the private updateProgressDialog()
method and, if you need persistent observability, replace it with the app's
structured logger (e.g., use an injected logger instead of console) while
leaving the existing this.progressDialogMessage.set(...) intact.
- Around line 53-72: The method updateBulkOperationProgress currently declares a
boolean return but returns nothing when !this.operationInProgress.value; update
it to always return a boolean by returning false in that early-exit branch
(e.g., replace `if (!this.operationInProgress.value) { return; }` with `if
(!this.operationInProgress.value) { return false; }`) so callers of
updateBulkOperationProgress get a consistent boolean; ensure no other code paths
change and keep the existing behavior for processedUpdateCount,
updateProgressDialog, and completeBulkOperation.

In @src/app/core/entity/entity-actions/entity-edit.service.ts:
- Around line 77-93: The bulk operation is started via
bulkOperationState.startBulkOperation(...) but completeBulkOperation() is only
called in the catch block, leaving the success path incomplete; after awaiting
entityMapper.saveAll(newEntities) and before returning the success object you
must call this.bulkOperationState.completeBulkOperation() (and ensure it runs
even if subsequent lines throw), so add the completeBulkOperation() call on the
success path (or refactor the try/catch into try/finally around saveAll to
always call this.bulkOperationState.completeBulkOperation()), referencing
bulkOperationState.startBulkOperation, entityMapper.saveAll, and
completeBulkOperation.
🧹 Nitpick comments (5)
src/app/core/entity/entity-actions/entity-edit.service.ts (1)

89-93: Suggest adding error logging for bulk operation failures.

While the error handling correctly completes the bulk operation and re-throws, adding logging would help diagnose bulk edit failures in production.

🔎 Proposed enhancement with error logging
     } catch (error) {
       // On error, complete bulk operation immediately
       this.bulkOperationState.completeBulkOperation();
+      console.error('Bulk edit operation failed:', error, { entityCount: newEntities.length });
       throw error;
     }

As per coding guidelines, Angular services should implement proper error handling and logging.

src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts (1)

9-18: Consider adding OnPush change detection strategy.

Per coding guidelines, components should use ChangeDetectionStrategy.OnPush for performance optimization. Since this component now uses Signals (which work well with OnPush), this would be a good addition.

🔎 Proposed fix
+import { Component, inject, Signal, ChangeDetectionStrategy } from "@angular/core";
-import { Component, inject, Signal } from "@angular/core";
 import { MAT_DIALOG_DATA, MatDialogModule } from "@angular/material/dialog";
 import { MatProgressBarModule } from "@angular/material/progress-bar";

 /**
  * A simple progress indicator dialog
  * used via the {@link ConfirmationDialogService}.
  */
 @Component({
   templateUrl: "./progress-dialog.component.html",
   imports: [MatProgressBarModule, MatDialogModule],
+  changeDetection: ChangeDetectionStrategy.OnPush,
 })
src/app/core/entity/entity-actions/entity-actions.service.ts (1)

362-380: Consider using saveAll for consistency with the archive method.

The undoArchive method still uses individual save calls within a forEach, which doesn't await properly (fire-and-forget). For consistency with the updated archive method and proper async handling, consider refactoring to use saveAll.

🔎 Proposed fix
   async undoArchive<E extends Entity>(entityParam: E | E[]) {
     let newEntities: E[] = Array.isArray(entityParam)
       ? entityParam
       : [entityParam];
     const originalEntities: E[] = newEntities.map((e) => e.copy());
-    newEntities.forEach(async (e) => {
-      e.inactive = false;
-      await this.entityMapper.save(e);
-    });
+    newEntities.forEach((e) => (e.inactive = false));
+
+    if (newEntities.length > 1) {
+      this.bulkOperationState.startBulkOperation(newEntities.length);
+      try {
+        await this.entityMapper.saveAll(newEntities);
+      } catch (error) {
+        this.bulkOperationState.completeBulkOperation();
+        throw error;
+      }
+    } else {
+      await this.entityMapper.save(newEntities[0]);
+    }
 
     this.showSnackbarConfirmationWithUndo(
src/app/core/entity/entity-actions/bulk-operation-state.service.ts (1)

22-22: Avoid any type for MatDialogRef.

Per coding guidelines, avoid using any. Consider typing this more specifically.

🔎 Proposed fix
+import { ProgressDialogComponent } from "../../common-components/confirmation-dialog/progress-dialog/progress-dialog.component";
 ...
-  private progressDialogRef: MatDialogRef<any> | null = null;
+  private progressDialogRef: MatDialogRef<ProgressDialogComponent> | null = null;
src/app/core/entity/entity-actions/entity-actions.service.spec.ts (1)

48-51: Mock setup is correct; consider adding assertions for bulk operation state calls in archive tests.

The mock is properly configured. However, the test for archiving multiple entities (lines 295-310) should verify that startBulkOperation and completeBulkOperation are called appropriately, since the implementation invokes these methods when processing multiple entities.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8fc578c and 054e003.

📒 Files selected for processing (11)
  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/entity-edit.service.ts
🧰 Additional context used
📓 Path-based instructions (18)
**/*.{component,service,directive,guard,interceptor,resolver,pipe}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use inject() function instead of constructor injection for dependencies

Files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
**/*.service.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.service.ts: Use providedIn: 'root' for singleton services in Angular
Implement proper error handling and logging in Angular services

Files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
**/*.{component,service}.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{component,service}.ts: Use update() or set() instead of mutate() when modifying signals in Angular
Create interfaces for configuration objects and let component classes implement them

Files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Use strict type checking with TypeScript and avoid any type; use unknown when type is uncertain
Prefer type inference in TypeScript when obvious

Files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
src/**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,js}: Use ESLint for linting (npm run lint)
Use Prettier for code formatting

Files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
src/app/core/**/*.{service,module}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Core system modules and services belong in src/app/core/

Files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
**/*.component.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.component.ts: Use standalone components (default behavior, do NOT set standalone: true)
Prefer input() and output() functions over @Input and @Output decorators in Angular components
Use signals for reactive state management with computed() for derived state
Set changeDetection: ChangeDetectionStrategy.OnPush for all components
Prefer inline templates for small components in Angular
Prefer Reactive Forms over Template-driven forms in Angular
Use NgOptimizedImage for static images instead of base64 encoded images
Use Angular Material components for UI consistency following Material Design guidelines
Implement OnPush change detection strategy for performance optimization
Use trackBy functions for lists in Angular templates for performance optimization

Files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
**/*.{component,directive}.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{component,directive}.ts: Do NOT use @HostBinding and @HostListener decorators; put host bindings inside the host object of @Component or @Directive decorator
Implement proper permissions checking via CASL integration using EntityAbility and DisableEntityOperationDirective

Files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
**/*.component.{ts,html}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.component.{ts,html}: All user-facing strings must be translatable using Angular i18n markers or $localize in Aam Digital
Follow existing translation key patterns in Aam Digital
Use Angular Material accessibility features in components

Files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
**/*entity*.{service,component}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use proper generics for entity types in TypeScript

Files:

  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
**/*entity*.service.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use entity services for data access and caching in Aam Digital

Files:

  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
**/*.component.html

📄 CodeRabbit inference engine (AGENTS.md)

**/*.component.html: Use native control flow (@if, @for, @switch) instead of structural directives (*ngIf, *ngFor, *ngSwitch)
Use class bindings instead of ngClass directive in Angular templates
Use style bindings instead of ngStyle directive in Angular templates
Keep templates simple and avoid complex logic in Angular templates
Use async pipe for observables in Angular templates instead of manual subscriptions

Files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
**/*.component.{scss,html}

📄 CodeRabbit inference engine (AGENTS.md)

Use global style classes from src/styles/globals/ (e.g., flex-row, margin-regular) instead of creating new custom styles

Files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
**/*.component.{html,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Follow WCAG guidelines for accessibility in Aam Digital

Files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
src/app/core/common-components/**/*.component.ts

📄 CodeRabbit inference engine (AGENTS.md)

Shared components belong in src/app/core/common-components/

Files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
**/*.{component,service}.spec.ts

📄 CodeRabbit inference engine (AGENTS.md)

Write unit tests for all new components and services using Jasmine/Karma

Files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.spec.ts: Mock dependencies properly using Angular testing utilities in unit tests
Use established testing patterns from the Aam Digital project in unit tests

Files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
**/*entity*.spec.ts

📄 CodeRabbit inference engine (AGENTS.md)

Test entity operations with proper data setup/teardown in unit tests

Files:

  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
🧠 Learnings (18)
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.{component,service}.ts : Use `update()` or `set()` instead of `mutate()` when modifying signals in Angular

Applied to files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.{component,service,directive,guard,interceptor,resolver,pipe}.ts : Use `inject()` function instead of constructor injection for dependencies

Applied to files:

  • src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.{ts,html} : All user-facing strings must be translatable using Angular i18n markers or `$localize` in Aam Digital

Applied to files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.ts : Use signals for reactive state management with `computed()` for derived state

Applied to files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.ts : Use Angular Material components for UI consistency following Material Design guidelines

Applied to files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.ts : Prefer `input()` and `output()` functions over `Input` and `Output` decorators in Angular components

Applied to files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.service.ts : Implement proper error handling and logging in Angular services

Applied to files:

  • src/app/core/admin/admin-overview/admin-overview.component.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*entity*.service.ts : Use entity services for data access and caching in Aam Digital

Applied to files:

  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*entity*.spec.ts : Test entity operations with proper data setup/teardown in unit tests

Applied to files:

  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity/entity-actions/entity-actions.service.ts
  • src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*entity*.{service,component}.ts : Use proper generics for entity types in TypeScript

Applied to files:

  • src/app/core/entity/entity-actions/entity-edit.service.ts
  • src/app/core/entity-list/entity-list/entity-list.component.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.{ts,html} : Use Angular Material accessibility features in components

Applied to files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.ts : Prefer Reactive Forms over Template-driven forms in Angular

Applied to files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.html : Use async pipe for observables in Angular templates instead of manual subscriptions

Applied to files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.component.ts : Prefer inline templates for small components in Angular

Applied to files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.spec.ts : Mock dependencies properly using Angular testing utilities in unit tests

Applied to files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.spec.ts : Use established testing patterns from the Aam Digital project in unit tests

Applied to files:

  • src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.{component,service}.spec.ts : Write unit tests for all new components and services using Jasmine/Karma

Applied to files:

  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to src/app/core/demo-data/**/*.ts : Provide demo data generators for new entities using `faker-js/faker` following existing demo data patterns

Applied to files:

  • src/app/core/entity/entity-actions/entity-actions.service.spec.ts
🧬 Code graph analysis (1)
src/app/core/entity-list/entity-list/entity-list.component.ts (1)
src/app/core/entity/model/entity-update.ts (1)
  • UpdatedEntity (7-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Seer Code Review
  • GitHub Check: qa / test-unit
  • GitHub Check: qa / test-e2e
  • GitHub Check: build-webapp
🔇 Additional comments (11)
src/app/core/admin/admin-overview/admin-overview.component.ts (1)

144-146: LGTM! Properly wraps localized message as Signal.

The change correctly adapts to the new showProgressDialog API by wrapping the localized string with signal(). This maintains i18n support while providing reactive message capabilities.

src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html (1)

2-2: LGTM! Template correctly calls signal accessor.

The change from {{ data.message }} to {{ message() }} properly consumes the Signal-based message, enabling reactive updates to the progress dialog title.

src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts (1)

5-5: LGTM! Test properly updated for Signal API.

The test correctly provides message: signal("test title") to match the new component API that expects a Signal. This follows proper Angular testing patterns.

Also applies to: 18-18

src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts (1)

71-77: LGTM! Signal migration improves reactivity.

The change from message: string to message: Signal<string> enables reactive progress message updates, which is beneficial for bulk operations that need to show dynamic progress. All callers have been properly updated to pass Signal<string> arguments (either as wrapping signal() or passing existing WritableSignal properties), and signal updates correctly use the set() method rather than mutate().

src/app/core/entity/entity-actions/entity-edit.service.ts (1)

77-81: saveAll() does not automatically update progress; additional instrumentation is needed for tracking.

The EntityMapperService.saveAll() method has no integration with BulkOperationStateService. Progress is only updated when list components receive entity change events and manually call updateBulkOperationProgress(). The current code starts a bulk operation but relies on external components to track completion—if no listeners are present, the progress dialog will not update or close automatically. Consider either: (1) instrumenting saveAll() to report progress directly, or (2) documenting that bulk edit operations require active listeners on entity update events for progress tracking to work.

src/app/core/entity-list/duplicate-records/duplicate-records.service.ts (1)

27-34: Bulk operation lifecycle properly integrated.

The bulk operation state management is correctly implemented with proper error handling. On success, completion is intentionally delegated to the entity-list component which tracks when UI rendering is complete before closing the progress dialog.

src/app/core/entity/entity-actions/entity-actions.service.ts (1)

336-347: Good implementation of bulk save for archive operation.

The branching logic correctly uses saveAll for multiple entities while preserving the single-entity path for performance. Error handling properly cleans up bulk operation state.

src/app/core/entity/entity-actions/bulk-operation-state.service.ts (1)

1-45: Well-structured service for coordinating bulk operations.

The service properly:

  • Uses providedIn: 'root' for singleton behavior
  • Implements OnDestroy for cleanup
  • Exposes both observable (isBulkOperationInProgress$) and synchronous (isBulkOperationInProgress()) access patterns
  • Uses signals for reactive progress message updates
src/app/core/entity/entity-actions/entity-actions.service.spec.ts (1)

295-310: Tests properly updated for bulk save behavior.

The test assertions correctly verify that saveAll is called once with all entities instead of multiple individual save calls.

src/app/core/entity-list/entity-list/entity-list.component.ts (2)

282-298: Bulk operation handling with render-aware completion.

The implementation correctly:

  • Buffers individual updates during bulk operations to avoid UI performance issues
  • Reloads all entities once the expected count is reached
  • Uses setTimeout + requestAnimationFrame to ensure UI rendering is complete before closing the progress dialog

This addresses the timing issue mentioned in past reviews where the progress bar would close before the table finished rendering.


46-46: Good typing improvement.

Importing and using UpdatedEntity<T> instead of any for the callback parameter aligns with strict typing guidelines.

Copy link
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

🤖 Fix all issues with AI agents
In @src/app/core/entity/entity-actions/bulk-operation-state.service.ts:
- Line 22: Replace the use of the unsafe any type for the dialog reference:
change the declaration of progressDialogRef from MatDialogRef<any> | null to
MatDialogRef<unknown> | null (keeping the | null) so the code uses stricter
typing while still allowing .close() to be called; update any imports/usages
referencing progressDialogRef if necessary to reflect the new generic type.
- Around line 37-45: startBulkOperation currently allows concurrent starts; add
a guard at the top of startBulkOperation to no-op (or return/throw) if an
operation is already in progress by checking operationInProgress (or the
existing progressDialogRef). If you decide to allow restart, first close the
orphaned dialogRef (if progressDialogRef exists/has close) and clear counters
before creating a new dialog; otherwise simply return early to prevent
overwriting expectedUpdateCount, processedUpdateCount, and progressDialogRef.
Ensure you reference startBulkOperation, operationInProgress, progressDialogRef,
confirmationDialog.showProgressDialog, expectedUpdateCount,
processedUpdateCount, and updateProgressDialog in your change so the logic and
dialog lifecycle are handled safely.
🧹 Nitpick comments (1)
src/app/core/entity/entity-actions/bulk-operation-state.service.ts (1)

37-45: Consider adding error handling for dialog operations.

If showProgressDialog throws an exception, the service state becomes inconsistent (operationInProgress is true but progressDialogRef is null). Wrapping the dialog call in a try-catch block would improve robustness.

🔎 Proposed refactor
   startBulkOperation(expectedCount?: number) {
     this.expectedUpdateCount = expectedCount || 0;
     this.processedUpdateCount = 0;
     this.operationInProgress.next(true);
     this.updateProgressDialog();
-    this.progressDialogRef = this.confirmationDialog.showProgressDialog(
-      this.progressDialogMessage,
-    );
+    try {
+      this.progressDialogRef = this.confirmationDialog.showProgressDialog(
+        this.progressDialogMessage,
+      );
+    } catch (error) {
+      console.error('Failed to show progress dialog', error);
+      this.completeBulkOperation();
+    }
   }

Based on coding guidelines, implement proper error handling in Angular services.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 054e003 and 3bf24ec.

📒 Files selected for processing (1)
  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{component,service,directive,guard,interceptor,resolver,pipe}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use inject() function instead of constructor injection for dependencies

Files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
**/*.service.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.service.ts: Use providedIn: 'root' for singleton services in Angular
Implement proper error handling and logging in Angular services

Files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
**/*.{component,service}.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{component,service}.ts: Use update() or set() instead of mutate() when modifying signals in Angular
Create interfaces for configuration objects and let component classes implement them

Files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Use strict type checking with TypeScript and avoid any type; use unknown when type is uncertain
Prefer type inference in TypeScript when obvious

Files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
src/**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,js}: Use ESLint for linting (npm run lint)
Use Prettier for code formatting

Files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
src/app/core/**/*.{service,module}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Core system modules and services belong in src/app/core/

Files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
🧠 Learnings (2)
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*entity*.service.ts : Use entity services for data access and caching in Aam Digital

Applied to files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
📚 Learning: 2025-11-26T16:20:52.119Z
Learnt from: CR
Repo: Aam-Digital/ndb-core PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T16:20:52.119Z
Learning: Applies to **/*.{component,service}.ts : Use `update()` or `set()` instead of `mutate()` when modifying signals in Angular

Applied to files:

  • src/app/core/entity/entity-actions/bulk-operation-state.service.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Seer Code Review
  • GitHub Check: qa / test-unit
  • GitHub Check: build-webapp
  • GitHub Check: qa / test-e2e
🔇 Additional comments (5)
src/app/core/entity/entity-actions/bulk-operation-state.service.ts (5)

1-19: LGTM: Service setup follows Angular best practices.

The service correctly uses providedIn: 'root' for singleton behavior and the inject() function for dependency injection, as per the coding guidelines.


77-86: LGTM: Getter methods are straightforward and correct.

The getter methods properly expose internal state for external monitoring of bulk operation progress.


91-95: LGTM: Progress dialog update uses correct signal API.

The method correctly uses set() to update the signal, following Angular best practices. The previous console.log statement has been removed.


103-111: LGTM: Cleanup logic is thorough.

The method properly resets all state variables and ensures the dialog reference is closed and nulled, preventing resource leaks.


113-119: LGTM: Proper lifecycle cleanup.

The ngOnDestroy hook correctly completes the BehaviorSubject and ensures any in-progress operation is cleaned up, following Angular best practices for service cleanup.

Copy link
Member

@sleidig sleidig left a comment

Choose a reason for hiding this comment

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

Works super fast now 🤩

Code looks good also. Great job 👍

@sleidig sleidig merged commit 3073613 into master Jan 7, 2026
16 of 17 checks passed
@sleidig sleidig deleted the refactor/bulk-edit-save branch January 7, 2026 17:58
@aam-digital-ci
Copy link
Collaborator

🎉 This PR is included in version 3.68.0-master.11 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@aam-digital-ci aam-digital-ci added the released on @master managed by CI (semantic-release) label Jan 7, 2026
sleidig added a commit that referenced this pull request Jan 9, 2026
by a batch save and avoiding intermittent reloads of the list
closes #2843

---------

Co-authored-by: Sebastian <[email protected]>
@aam-digital-ci
Copy link
Collaborator

🎉 This PR is included in version 3.68.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@aam-digital-ci aam-digital-ci added the released managed by CI (semantic-release) label Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released on @master managed by CI (semantic-release) released managed by CI (semantic-release)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bulk Edit: Changes are applied very slowly, one by one

4 participants