From e16f8671dba29dd0c6cbe1c92d599888e7b349b6 Mon Sep 17 00:00:00 2001 From: "maxim.gorbatyuk" Date: Tue, 2 Apr 2024 22:11:49 +0500 Subject: [PATCH] CSV downloader --- .../interview-page.component.ts | 13 +++--------- .../salaries-chart.component.html | 21 ++++++++++++++----- .../salaries-chart.component.ts | 20 ++++++++++++++++++ src/app/services/user-salaries.service.ts | 8 +++++++ .../value-objects/file-download-anchor.ts | 11 ++++++++++ 5 files changed, 58 insertions(+), 15 deletions(-) create mode 100644 src/app/shared/value-objects/file-download-anchor.ts diff --git a/src/app/modules/interviews/components/interview-page/interview-page.component.ts b/src/app/modules/interviews/components/interview-page/interview-page.component.ts index c839fbb3..9335babb 100644 --- a/src/app/modules/interviews/components/interview-page/interview-page.component.ts +++ b/src/app/modules/interviews/components/interview-page/interview-page.component.ts @@ -8,6 +8,7 @@ import { ConfirmMsg } from '@shared/components/dialogs/models/confirm-msg'; import { DialogMessage } from '@shared/components/dialogs/models/dialog-message'; import { ActivatedRouteExtended } from '@shared/routes/activated-route-extended'; import { untilDestroyed } from '@shared/subscriptions/until-destroyed'; +import { FileDownloadAnchor } from '@shared/value-objects/file-download-anchor'; @Component({ selector: 'app-interview-page', @@ -84,7 +85,7 @@ export class InterviewPageComponent implements OnInit, OnDestroy { exportAsPDF(): void { if (this.downloadedFile != null) { - this.outputFile(); + new FileDownloadAnchor(this.downloadedFile).execute(`${this.interview!.candidateName}_${this.interview!.id}.pdf`); return; } @@ -93,18 +94,10 @@ export class InterviewPageComponent implements OnInit, OnDestroy { .pipe(untilDestroyed(this)) .subscribe((file) => { this.downloadedFile = file; - this.outputFile(); + new FileDownloadAnchor(this.downloadedFile).execute(`${this.interview!.candidateName}_${this.interview!.id}.pdf`); }); } - private outputFile(): void { - const url = window.URL.createObjectURL(this.downloadedFile!); - const a = document.createElement('a'); - a.href = url; - a.download = `${this.interview!.candidateName}_${this.interview!.id}.pdf`; - a.click(); - } - private setTitle(): void { this.pageTitle = `Interview with ${this.interview!.candidateName}`; this.title.setTitle(this.pageTitle); diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html index 4c1b827c..5cc3e219 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html +++ b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html @@ -232,11 +232,22 @@ -
-
Идея подсмотрена у сервиса Habr.Карьера, за что им большая благодарность.
-
Проект opensource, исходный код доступен на Github.
-
- Вы можете поддержать проект на boosty. Любая поддержка будет ценна. +
+
+
+ +
+
+
Сырые данные можно выгрузить в
+
В файл будут записаны все данные, несмотря на примененные на странице фильтры.
+
+ +
+
Идея подсмотрена у сервиса Habr.Карьера, за что им большая благодарность.
+
Проект opensource, исходный код доступен на Github.
+
+ Вы можете поддержать проект на boosty. Любая поддержка будет ценна. +
diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts index 741e4c09..4a50e077 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts @@ -16,6 +16,7 @@ import { CurrentUserSalaryLabelData } from './current-user-salary-label-data'; import { MetaTagService } from '@services/meta-tag.service'; import { LabelEntityDto } from '@services/label-entity.model'; import { ConvertObjectToHttpParams } from '@shared/value-objects/convert-object-to-http'; +import { FileDownloadAnchor } from '@shared/value-objects/file-download-anchor'; @Component({ templateUrl: './salaries-chart.component.html', @@ -34,6 +35,8 @@ export class SalariesChartComponent implements OnInit, OnDestroy { industries: Array = []; professions: Array = []; + downloadedFile: File | null = null; + showDataStub = false; openAddSalaryModal = false; openEditCurrentSalaryModal = false; @@ -188,6 +191,23 @@ export class SalariesChartComponent implements OnInit, OnDestroy { this.meta.returnDefaultMetaTags(); } + downloadCsv(): void { + this.gtag.event('salaries_csv_download', 'salary_chart'); + + if (this.downloadedFile != null) { + new FileDownloadAnchor(this.downloadedFile).execute(null); + return; + } + + this.service + .downloadCsv() + .pipe(untilDestroyed(this)) + .subscribe((file) => { + this.downloadedFile = file; + new FileDownloadAnchor(this.downloadedFile).execute(null); + }); + } + private loadChartWithFilter(data: SalaryChartGlobalFiltersData | null = null): void { this.service.charts({ grade: data?.grade ?? null, diff --git a/src/app/services/user-salaries.service.ts b/src/app/services/user-salaries.service.ts index 06ae1780..21d0f670 100644 --- a/src/app/services/user-salaries.service.ts +++ b/src/app/services/user-salaries.service.ts @@ -177,4 +177,12 @@ export class UserSalariesService { delete(dataId: string): Observable { return this.api.delete(this.root + dataId); } + + downloadCsv(): Observable { + const httpOptions = { + responseType: 'blob' as 'json' + }; + + return this.api.get(this.root + '/export', httpOptions); + } } diff --git a/src/app/shared/value-objects/file-download-anchor.ts b/src/app/shared/value-objects/file-download-anchor.ts new file mode 100644 index 00000000..f45b62b6 --- /dev/null +++ b/src/app/shared/value-objects/file-download-anchor.ts @@ -0,0 +1,11 @@ +export class FileDownloadAnchor { + constructor(private readonly file: File) {} + + execute(filename: string | null): void { + const url = window.URL.createObjectURL(this.file); + const a = document.createElement('a'); + a.href = url; + a.download = filename ?? this.file.name; + a.click(); + } +}