Skip to content

Download export should show loading indicator #3913

Merged
sleidig merged 8 commits intomasterfrom
fix/download-indicator-progress
May 6, 2026
Merged

Download export should show loading indicator #3913
sleidig merged 8 commits intomasterfrom
fix/download-indicator-progress

Conversation

@Abhinegi2
Copy link
Copy Markdown
Member

@Abhinegi2 Abhinegi2 commented May 5, 2026

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 reformatting changes 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.
    • (PR = "Ready for Review" does not immediately request a manual review yet, first complete the further checks below)
  • add label "Final Review" to trigger Argos visual review and CodeRabbit AI review (can also be done while still in Draft)
  • 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

    • Export dialog shows a progress indicator and disables actions while a download is in progress.
    • A clear error message is displayed in the dialog if a download fails.
  • Bug Fixes

    • Download and Cancel buttons are disabled during export to prevent duplicate actions.
    • Export validation improved to skip invalid/blank entries before exporting.

@Abhinegi2 Abhinegi2 self-assigned this May 5, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Warning

Rate limit exceeded

@Abhinegi2 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 14 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d45d4cf0-63e1-4f76-80b0-739c3be62697

📥 Commits

Reviewing files that changed from the base of the PR and between 09aa7e8 and 04c4019.

📒 Files selected for processing (2)
  • src/app/core/export/export-dialog/export-dialog.component.html
  • src/app/core/export/export-dialog/export-dialog.component.ts
📝 Walkthrough

Walkthrough

Export dialog gains loading state and error signal; template shows a progress bar and disables Download/Cancel while loading. download() now sets loading, delays briefly, selects filtered or all entities, triggers download, closes on success, and logs/sets a localized error on failure. QueryService.toEntities rejects falsy ids.

Changes

Export Dialog: loading, error, wiring

Layer / File(s) Summary
Signals & State
src/app/core/export/export-dialog/export-dialog.component.ts
Adds isLoading: Signal<boolean> and `downloadError: Signal<string
Imports & Component Metadata
src/app/core/export/export-dialog/export-dialog.component.ts
Adds MatFormFieldModule and MatProgressBarModule to component imports; imports Logging service.
Core Logic
src/app/core/export/export-dialog/export-dialog.component.ts
Replaces download() with implementation that sets/clears isLoading, clears downloadError, awaits a short delay, selects filteredData or allEntities based on scope, calls downloadService.triggerDownload, closes dialog on success, and logs/sets a localized error on failure (finally resets loading).
Template / UX
src/app/core/export/export-dialog/export-dialog.component.html
Renders an indeterminate mat-progress-bar when isLoading(); disables Download and Cancel buttons during loading; conditionally shows downloadError() in a mat-error.

Query Service: id validation

Layer / File(s) Summary
Data Validation
src/app/core/export/query.service.ts
toEntities filter updated to reject `typeof id !== "string"

Sequence Diagram

sequenceDiagram
    participant User
    participant ExportDialog
    participant QueryService
    participant DownloadService
    participant Logging

    User->>ExportDialog: Click Download
    ExportDialog->>ExportDialog: set isLoading = true
    ExportDialog->>ExportDialog: await short delay
    ExportDialog->>QueryService: toEntities(filter ids)
    QueryService-->>ExportDialog: return resolved entities
    ExportDialog->>DownloadService: triggerDownload(data)
    alt success
        DownloadService-->>ExportDialog: success
        ExportDialog->>ExportDialog: close dialog
    else error
        DownloadService-->>ExportDialog: throw error
        ExportDialog->>Logging: log warning
        ExportDialog-->>ExportDialog: set downloadError(msg)
    end
    ExportDialog->>ExportDialog: set isLoading = false
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related PRs

Suggested reviewers

  • sadaf895
  • sleidig

Poem

🐰 I press the button, watch the bar glow bright,
Buttons nap while bytes take flight,
If errors leap, I log and sigh,
Then show a message, soft and spry,
A hopping download — done just right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description references the linked issue (#3900) and includes the PR checklist template, but many checklist items are unchecked, and no detailed explanation of changes is provided beyond the issue reference. Add a brief explanation of what was implemented (loading indicator, button disabling, error handling) and check off relevant checklist items to clarify the PR's completion status.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a loading indicator to the download export dialog, which is the primary objective of the PR.
Linked Issues check ✅ Passed The code changes fully implement the requirements: isLoading signal disables buttons [#3900], loading indicator display in template [#3900], and error handling with downloadError display [#3900].
Out of Scope Changes check ✅ Passed All changes are scope-aligned: template updates for UI loading state, TypeScript enhancements for loading/error signals, and a minor query service fix for empty ID validation that supports robustness.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/download-indicator-progress

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

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

@Abhinegi2 Abhinegi2 marked this pull request as ready for review May 5, 2026 08:05
@Abhinegi2 Abhinegi2 added the Final Review Triggers CodeRabbit AI review and Argos visual review label May 5, 2026
@argos-ci
Copy link
Copy Markdown

argos-ci Bot commented May 5, 2026

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

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - May 6, 2026, 6:45 AM

@github-actions github-actions Bot removed the Final Review Triggers CodeRabbit AI review and Argos visual review label May 5, 2026
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.

Caution

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

⚠️ Outside diff range comments (1)
src/app/core/export/export-dialog/export-dialog.component.html (1)

43-61: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Download and Cancel buttons correctly disabled during loading — note: dialog-close X in the title header is unguarded.

The [disabled]="isLoading()" bindings on both action buttons are correct: disabled native <button> elements suppress click events, so MatDialogClose on the Cancel button will not fire while loading.

However, the <app-dialog-close mat-dialog-close> in the <h1> title remains fully interactive while isLoading() is true. Clicking it mid-download closes the dialog (the background download still completes via the browser), but the subsequent this.dialogRef.close() / alertService.addWarning(...) calls in download() will execute against an already-closed dialog. This is a minor UX inconsistency relative to the stated goal of "disable buttons while the export is being processed."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/core/export/export-dialog/export-dialog.component.html` around lines
43 - 61, The title's close control (<app-dialog-close mat-dialog-close>) remains
interactive during export; prevent closing while loading by wiring the same
loading guard used on the action buttons: add a disabled binding or a click
guard to the title close control (e.g., change <app-dialog-close
mat-dialog-close> to include [disabled]="isLoading()" or replace it with a
button that checks isLoading() in (click) and only calls dialogRef.close() when
false); keep the existing download() and alertService/dialogRef calls unchanged
but ensure the title control cannot close the dialog while isLoading() is true.
🧹 Nitpick comments (2)
src/app/core/export/export-dialog/export-dialog.component.ts (1)

78-82: ⚡ Quick win

Replace console.error with the Logging service.

console.error bypasses the application's centralized logging infrastructure. The codebase already uses Logging.error(...) / Logging.warn(...) (see download.service.ts). As per coding guidelines for *.component.ts, use Logging from #src/app/core/logging/logging.service instead of any console.* call.

♻️ Proposed fix
+import { Logging } from "#src/app/core/logging/logging.service";
 ...
     } catch (e) {
-      console.error("Export download failed:", e);
+      Logging.error("Export download failed:", e);
       this.alertService.addWarning(

As per coding guidelines: "Use Logging service from #src/app/core/logging/logging.service instead of console.log" (for **/*.component.ts).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/core/export/export-dialog/export-dialog.component.ts` around lines 78
- 82, In ExportDialogComponent's catch block replace the direct console.error
call with the centralized Logging service: import Logging from
`#src/app/core/logging/logging.service` and call Logging.error("Export download
failed:", e) (or equivalent signature used elsewhere) then keep the existing
this.alertService.addWarning(...) behavior; remove the console.error call so all
errors go through Logging.error in the export download handler.
src/app/core/export/export-dialog/export-dialog.component.html (1)

6-8: ⚡ Quick win

Progress bar placement causes a layout shift on toggle.

Placing the mat-progress-bar conditionally between the title and the dialog content means the content area shifts down ~4 px when loading starts and snaps back up when it ends. Using visibility instead of @if keeps space reserved and avoids the reflow:

💡 Proposed alternative to avoid layout shift
-@if (isLoading()) {
-  <mat-progress-bar mode="indeterminate"></mat-progress-bar>
-}
+<mat-progress-bar
+  [style.visibility]="isLoading() ? 'visible' : 'hidden'"
+  mode="indeterminate"
+></mat-progress-bar>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/core/export/export-dialog/export-dialog.component.html` around lines
6 - 8, The progress bar is conditionally rendered with "@if (isLoading())"
causing a layout shift; instead always render the <mat-progress-bar> in
export-dialog.component.html and toggle its visibility (e.g., bind
[style.visibility] or [hidden] to isLoading()) so space is reserved while it's
invisible—locate the mat-progress-bar element near the dialog title and replace
the conditional rendering that uses isLoading() with a visibility binding tied
to the same isLoading() method.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/app/core/export/export-dialog/export-dialog.component.html`:
- Around line 43-61: The title's close control (<app-dialog-close
mat-dialog-close>) remains interactive during export; prevent closing while
loading by wiring the same loading guard used on the action buttons: add a
disabled binding or a click guard to the title close control (e.g., change
<app-dialog-close mat-dialog-close> to include [disabled]="isLoading()" or
replace it with a button that checks isLoading() in (click) and only calls
dialogRef.close() when false); keep the existing download() and
alertService/dialogRef calls unchanged but ensure the title control cannot close
the dialog while isLoading() is true.

---

Nitpick comments:
In `@src/app/core/export/export-dialog/export-dialog.component.html`:
- Around line 6-8: The progress bar is conditionally rendered with "@if
(isLoading())" causing a layout shift; instead always render the
<mat-progress-bar> in export-dialog.component.html and toggle its visibility
(e.g., bind [style.visibility] or [hidden] to isLoading()) so space is reserved
while it's invisible—locate the mat-progress-bar element near the dialog title
and replace the conditional rendering that uses isLoading() with a visibility
binding tied to the same isLoading() method.

In `@src/app/core/export/export-dialog/export-dialog.component.ts`:
- Around line 78-82: In ExportDialogComponent's catch block replace the direct
console.error call with the centralized Logging service: import Logging from
`#src/app/core/logging/logging.service` and call Logging.error("Export download
failed:", e) (or equivalent signature used elsewhere) then keep the existing
this.alertService.addWarning(...) behavior; remove the console.error call so all
errors go through Logging.error in the export download handler.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 988bae4f-c8e6-4282-b682-9ee5faaa9d70

📥 Commits

Reviewing files that changed from the base of the PR and between b176f14 and 84c3ee9.

📒 Files selected for processing (3)
  • src/app/core/export/export-dialog/export-dialog.component.html
  • src/app/core/export/export-dialog/export-dialog.component.ts
  • src/app/core/export/query.service.ts

@Abhinegi2 Abhinegi2 added the Final Review Triggers CodeRabbit AI review and Argos visual review label May 5, 2026
@github-actions github-actions Bot removed the Final Review Triggers CodeRabbit AI review and Argos visual review label May 5, 2026
@Abhinegi2 Abhinegi2 requested a review from sadaf895 May 5, 2026 10:31
Copy link
Copy Markdown
Contributor

@sadaf895 sadaf895 left a comment

Choose a reason for hiding this comment

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

Looks good to me.

Comment thread src/app/core/export/export-dialog/export-dialog.component.ts Outdated
Comment thread src/app/core/export/export-dialog/export-dialog.component.ts Outdated
@Abhinegi2 Abhinegi2 added the Final Review Triggers CodeRabbit AI review and Argos visual review label May 6, 2026
@github-actions github-actions Bot removed the Final Review Triggers CodeRabbit AI review and Argos visual review label May 6, 2026
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

♻️ Duplicate comments (1)
src/app/core/export/export-dialog/export-dialog.component.html (1)

54-65: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Error message is still displayed after (below) the buttons, not above them

The downloadError block at line 63 is rendered after the Cancel button inside mat-dialog-actions, meaning the error appears below the buttons. The previous review specifically requested the error be shown above the buttons for better visibility.

Move the error display to just before the mat-dialog-actions block (or at the bottom of mat-dialog-content) so it's visible without scrolling past the action bar.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/core/export/export-dialog/export-dialog.component.html` around lines
54 - 65, The downloadError() mat-error block is currently placed inside
mat-dialog-actions after the Cancel button, so move the error display out of the
actions and place it immediately before the <mat-dialog-actions> block (or at
the bottom of <mat-dialog-content>) so the error appears above the action
buttons; update the template to render downloadError() (the mat-error element)
above the Cancel button (which uses mat-dialog-close and
[disabled]="isLoading()") and ensure binding remains {{ downloadError() }}.
🧹 Nitpick comments (1)
src/app/core/export/export-dialog/export-dialog.component.ts (1)

13-13: ⚡ Quick win

MatFormFieldModule is only needed if mat-error is used correctly inside a mat-form-field

The sole reason this module is imported is to support <mat-error> in the template, but <mat-error> is designed exclusively to be a child of <mat-form-field>. Once the template-side issue (see below) is fixed by replacing <mat-error> with an inline error span, this import becomes unused and should be removed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/core/export/export-dialog/export-dialog.component.ts` at line 13, The
MatFormFieldModule import is now unused because <mat-error> will be replaced
with an inline error span; remove the import of MatFormFieldModule and any
references to it in this file (e.g., any NgModule or component-level imports
that list MatFormFieldModule) so there are no unused Angular Material module
imports left (target the MatFormFieldModule symbol and any occurrences in the
file).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/core/export/export-dialog/export-dialog.component.html`:
- Around line 63-65: The download error display should be moved out of the
dialog actions and avoid using <mat-error> outside a <mat-form-field>: relocate
the conditional error UI from inside mat-dialog-actions to the top of
mat-dialog-content (above buttons), replace the current `@if`(downloadError())
block with an Angular structural conditional (e.g. *ngIf="downloadError()") and
render a plain element (e.g. <div> or <p>) with role="alert" and a class that
applies the Material error color (or color="warn" via component styles) instead
of <mat-error>; update the template where downloadError() is referenced and add
a CSS rule in the component stylesheet to style the error text for accessibility
and visual parity.

In `@src/app/core/export/export-dialog/export-dialog.component.ts`:
- Around line 83-85: The template literal passes an expression with type unknown
(caught error `e`) which violates strict template-expression rules; update the
call to this.downloadError.set(...) to convert `e` to a string safely (e.g., use
the existing `e instanceof Error ? e.message : String(e)` or check typeof e ===
'string' ? e : String(e)) so the value inside the template literal is strictly a
string; locate the `downloadError.set` invocation in export-dialog.component.ts
and replace the ternary expression with a string-coercing alternative to satisfy
type-checking.

---

Duplicate comments:
In `@src/app/core/export/export-dialog/export-dialog.component.html`:
- Around line 54-65: The downloadError() mat-error block is currently placed
inside mat-dialog-actions after the Cancel button, so move the error display out
of the actions and place it immediately before the <mat-dialog-actions> block
(or at the bottom of <mat-dialog-content>) so the error appears above the action
buttons; update the template to render downloadError() (the mat-error element)
above the Cancel button (which uses mat-dialog-close and
[disabled]="isLoading()") and ensure binding remains {{ downloadError() }}.

---

Nitpick comments:
In `@src/app/core/export/export-dialog/export-dialog.component.ts`:
- Line 13: The MatFormFieldModule import is now unused because <mat-error> will
be replaced with an inline error span; remove the import of MatFormFieldModule
and any references to it in this file (e.g., any NgModule or component-level
imports that list MatFormFieldModule) so there are no unused Angular Material
module imports left (target the MatFormFieldModule symbol and any occurrences in
the file).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ebcdd9ab-05bb-444b-8334-9f79658a3d52

📥 Commits

Reviewing files that changed from the base of the PR and between 84c3ee9 and 09aa7e8.

📒 Files selected for processing (2)
  • src/app/core/export/export-dialog/export-dialog.component.html
  • src/app/core/export/export-dialog/export-dialog.component.ts

Comment thread src/app/core/export/export-dialog/export-dialog.component.html Outdated
Comment thread src/app/core/export/export-dialog/export-dialog.component.ts
Abhinegi2 and others added 2 commits May 6, 2026 11:59
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@Abhinegi2 Abhinegi2 added the Final Review Triggers CodeRabbit AI review and Argos visual review label May 6, 2026
@github-actions github-actions Bot removed the Final Review Triggers CodeRabbit AI review and Argos visual review label May 6, 2026
Copy link
Copy Markdown
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.

Not very pretty error message 😊 but otherwise good. Thanks!

@sleidig sleidig merged commit f97ffed into master May 6, 2026
18 checks passed
@sleidig sleidig deleted the fix/download-indicator-progress branch May 6, 2026 07:58
@aam-digital-ci
Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 3.79.1-master.2 🎉

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 May 6, 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)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Download export should show loading indicator

4 participants