diff --git a/src/app/core/export/export-dialog/export-dialog.component.html b/src/app/core/export/export-dialog/export-dialog.component.html index bcef35a6dd..dd5682b94c 100644 --- a/src/app/core/export/export-dialog/export-dialog.component.html +++ b/src/app/core/export/export-dialog/export-dialog.component.html @@ -3,6 +3,10 @@

+@if (isLoading()) { + +} +

Format

}
+@if (downloadError()) { + {{ downloadError() }} +} +
-
diff --git a/src/app/core/export/export-dialog/export-dialog.component.ts b/src/app/core/export/export-dialog/export-dialog.component.ts index 2ee774aa6a..7e01ba06b4 100644 --- a/src/app/core/export/export-dialog/export-dialog.component.ts +++ b/src/app/core/export/export-dialog/export-dialog.component.ts @@ -10,8 +10,11 @@ import { MatDialogRef, } from "@angular/material/dialog"; import { MatButtonModule } from "@angular/material/button"; +import { MatFormFieldModule } from "@angular/material/form-field"; +import { MatProgressBarModule } from "@angular/material/progress-bar"; import { MatRadioModule } from "@angular/material/radio"; import { FormsModule } from "@angular/forms"; +import { Logging } from "../../logging/logging.service"; import { DialogCloseComponent } from "../../common-components/dialog-close/dialog-close.component"; import { DownloadService, @@ -41,6 +44,8 @@ export interface ExportDialogData { imports: [ MatDialogModule, MatButtonModule, + MatFormFieldModule, + MatProgressBarModule, MatRadioModule, FormsModule, DialogCloseComponent, @@ -54,18 +59,32 @@ export class ExportDialogComponent { format = signal("csv"); scope = signal<"filtered" | "all">("filtered"); + isLoading = signal(false); + downloadError = signal(null); async download() { - const exportData = - this.data.filteredData && this.scope() === "filtered" - ? this.data.filteredData - : this.data.allEntities; - await this.downloadService.triggerDownload( - exportData, - this.format(), - this.data.filename, - this.data.exportConfig, - ); - this.dialogRef.close(); + this.isLoading.set(true); + this.downloadError.set(null); + await new Promise((resolve) => setTimeout(resolve)); + try { + const exportData = + this.data.filteredData && this.scope() === "filtered" + ? this.data.filteredData + : this.data.allEntities; + await this.downloadService.triggerDownload( + exportData, + this.format(), + this.data.filename, + this.data.exportConfig, + ); + this.dialogRef.close(); + } catch (e) { + Logging.warn("Export download failed:", e); + this.downloadError.set( + $localize`Download failed [${e instanceof Error ? e.message : String(e)}]`, + ); + } finally { + this.isLoading.set(false); + } } } diff --git a/src/app/core/export/query.service.ts b/src/app/core/export/query.service.ts index 76e39a1ca2..fa1482ed77 100644 --- a/src/app/core/export/query.service.ts +++ b/src/app/core/export/query.service.ts @@ -280,7 +280,7 @@ export class QueryService { return ids .filter((id) => { - if (typeof id !== "string") { + if (typeof id !== "string" || !id) { console.debug("invalid entity id in Query :toEntities", id); return false; }