Skip to content
This repository was archived by the owner on Sep 21, 2025. It is now read-only.

Commit 54207d1

Browse files
authored
feat: export data (#80)
1 parent 65474a3 commit 54207d1

File tree

10 files changed

+1837
-1901
lines changed

10 files changed

+1837
-1901
lines changed

.github/workflows/deploy.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ jobs:
1717

1818
- name: Install pnpm
1919
uses: pnpm/action-setup@v4
20-
with:
21-
version: 9.15.1
2220

2321
- name: Setup Node.js
2422
uses: actions/setup-node@v4

.github/workflows/pull_request.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ jobs:
1919

2020
- name: Install pnpm
2121
uses: pnpm/action-setup@v4
22-
with:
23-
version: 9.15.1
2422

2523
- name: Setup Node.js
2624
uses: actions/setup-node@v4
@@ -41,8 +39,6 @@ jobs:
4139

4240
- name: Install pnpm
4341
uses: pnpm/action-setup@v4
44-
with:
45-
version: 9.15.1
4642

4743
- name: Setup Node.js
4844
uses: actions/setup-node@v4
@@ -72,8 +68,6 @@ jobs:
7268

7369
- name: Install pnpm
7470
uses: pnpm/action-setup@v4
75-
with:
76-
version: 9.15.1
7771

7872
- name: Setup Node.js
7973
uses: actions/setup-node@v4

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
44

5+
## [3.1.0](https://github.com/hjbugajski/applicationtrackr/compare/v3.0.1...v3.1.0) (2025-06-08)
6+
7+
### Features
8+
9+
- export data ([14c1b01](https://github.com/hjbugajski/applicationtrackr/commit/14c1b0193f0a31e30cfd89b50384c53d432738e9))
10+
511
## [3.0.1](https://github.com/hjbugajski/applicationtrackr/compare/v3.0.0...v3.0.1) (2024-12-26)
612

713
### Bug Fixes

package.json

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "applicationtrackr",
3-
"version": "3.0.1",
3+
"version": "3.1.0",
44
"scripts": {
55
"ng": "ng",
66
"start": "ng serve",
@@ -26,46 +26,47 @@
2626
"prerelease:major": "npm run bump:major"
2727
},
2828
"private": true,
29-
"packageManager": "pnpm@9.15.1",
29+
"packageManager": "pnpm@10.11.0",
3030
"dependencies": {
31-
"@angular/animations": "^18",
32-
"@angular/cdk": "^18",
33-
"@angular/common": "^18",
34-
"@angular/compiler": "^18",
35-
"@angular/core": "^18",
36-
"@angular/fire": "^18",
37-
"@angular/forms": "^18",
38-
"@angular/material": "^18",
39-
"@angular/platform-browser": "^18",
40-
"@angular/platform-browser-dynamic": "^18",
41-
"@angular/router": "^18",
42-
"rxjs": "^7",
43-
"tslib": "^2",
31+
"@angular/animations": "^18.2.13",
32+
"@angular/cdk": "^18.2.14",
33+
"@angular/common": "^18.2.13",
34+
"@angular/compiler": "^18.2.13",
35+
"@angular/core": "^18.2.13",
36+
"@angular/fire": "^18.0.1",
37+
"@angular/forms": "^18.2.13",
38+
"@angular/material": "^18.2.14",
39+
"@angular/platform-browser": "^18.2.13",
40+
"@angular/platform-browser-dynamic": "^18.2.13",
41+
"@angular/router": "^18.2.13",
42+
"rxjs": "^7.8.2",
43+
"tslib": "^2.8.1",
4444
"zone.js": "~0.14.10"
4545
},
4646
"devDependencies": {
47-
"@angular-devkit/build-angular": "^18",
48-
"@angular/cli": "^18",
49-
"@angular/compiler-cli": "^18",
50-
"@eslint/js": "^9.17.0",
51-
"@types/jasmine": "^5",
52-
"@types/node": "^20",
47+
"@angular-devkit/build-angular": "^18.2.19",
48+
"@angular-eslint/builder": "^18.4.3",
49+
"@angular/cli": "^18.2.19",
50+
"@angular/compiler-cli": "^18.2.13",
51+
"@eslint/js": "^9.28.0",
52+
"@types/jasmine": "^5.1.8",
53+
"@types/node": "^20.19.0",
5354
"angular-eslint": "18.4.3",
54-
"commit-and-tag-version": "^12",
55-
"eslint": "^9.15.0",
56-
"jasmine-core": "^5",
57-
"karma": "^6",
58-
"karma-chrome-launcher": "^3",
59-
"karma-coverage": "^2",
60-
"karma-jasmine": "^5",
61-
"karma-jasmine-html-reporter": "^2",
62-
"prettier": "^3",
63-
"stylelint": "^16",
64-
"stylelint-config-clean-order": "^6",
65-
"stylelint-config-standard-scss": "^14",
55+
"commit-and-tag-version": "^12.5.1",
56+
"eslint": "^9.28.0",
57+
"jasmine-core": "^5.8.0",
58+
"karma": "^6.4.4",
59+
"karma-chrome-launcher": "^3.2.0",
60+
"karma-coverage": "^2.2.1",
61+
"karma-jasmine": "^5.1.0",
62+
"karma-jasmine-html-reporter": "^2.1.0",
63+
"prettier": "^3.5.3",
64+
"stylelint": "^16.20.0",
65+
"stylelint-config-clean-order": "^6.1.0",
66+
"stylelint-config-standard-scss": "^14.0.0",
6667
"typescript": "~5.5.4",
6768
"typescript-eslint": "8.16.0",
68-
"version-bump-prompt": "^6"
69+
"version-bump-prompt": "^6.1.0"
6970
},
7071
"commit-and-tag-version": {
7172
"scripts": {

pnpm-lock.yaml

Lines changed: 1726 additions & 1858 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
onlyBuiltDependencies:
2+
- esbuild
3+
- lmdb
4+
- msgpackr-extract
5+
- nice-napi
6+
- protobufjs

src/app/settings/about/about.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="settings-section">
22
<h2 class="settings-section-header">About</h2>
3-
<p>Version 3.0.1</p>
3+
<p>Version 3.1.0</p>
44
<p>
55
<a href="https://applicationtrackr.io" target="_blank" rel="noreferrer"
66
>ApplicationTrackr Website</a

src/app/settings/account/account.component.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,23 @@ <h2 class="settings-section-header">Account</h2>
1111
<div class="at-caption">Signed in with {{ providerDisplay }}</div>
1212
</div>
1313

14+
<!-- Export data -->
15+
<div class="settings-section">
16+
<h2 class="settings-section-header">Export data</h2>
17+
<at-alert class="at-text primary" [color]="colors.Accent">
18+
<div message>
19+
Do not reload the page or navigate away while the export is in progress. Doing so may result
20+
in an incomplete export.
21+
</div>
22+
</at-alert>
23+
<button mat-flat-button color="accent" [disabled]="isBulkExportLoading" (click)="bulkExport()">
24+
<div *ngIf="isBulkExportLoading" class="loading-spinner-in-button">
25+
<mat-spinner color="accent" diameter="24"></mat-spinner>
26+
</div>
27+
<ng-container *ngIf="!isBulkExportLoading">Export</ng-container>
28+
</button>
29+
</div>
30+
1431
<ng-container *ngIf="provider === providers.Password">
1532
<!-- Update email address -->
1633
<div class="settings-section">

src/app/settings/account/account.component.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { AuthModes } from '~enums/auth-modes.enum';
1414
import { Colors } from '~enums/colors.enum';
1515
import { Providers } from '~enums/providers.enum';
1616
import { AuthService } from '~services/auth/auth.service';
17+
import { FirebaseFunctionsService } from '~services/firebase-functions/firebase-functions.service';
18+
import { NotificationService } from '~services/notification/notification.service';
1719
import { CustomValidators, getEmailError, getPasswordError } from '~utils/custom-validators';
1820

1921
@Component({
@@ -27,6 +29,7 @@ export class AccountComponent implements OnDestroy {
2729
Validators.pattern('delete account and data'),
2830
]);
2931
public isLoading = false;
32+
public isBulkExportLoading = false;
3033
public isUpdateEmailLoading = false;
3134
public provider: Providers | undefined;
3235
public reauthenticated = false;
@@ -43,6 +46,8 @@ export class AccountComponent implements OnDestroy {
4346
private auth: Auth,
4447
private authService: AuthService,
4548
private changeDetectorRef: ChangeDetectorRef,
49+
private firebaseFunctionsService: FirebaseFunctionsService,
50+
private notificationsService: NotificationService,
4651
) {
4752
this.subscriptions = authState(this.auth).subscribe((user) => {
4853
this.user = user;
@@ -84,6 +89,38 @@ export class AccountComponent implements OnDestroy {
8489
return Providers;
8590
}
8691

92+
public async bulkExport(): Promise<void> {
93+
this.isBulkExportLoading = true;
94+
this.notificationsService.show(Colors.Neutral, 'Exporting data...');
95+
96+
try {
97+
const exportData = await this.firebaseFunctionsService.bulkExport();
98+
99+
this.downloadJsonFile(exportData, 'job-board-export.json');
100+
this.notificationsService.showSuccess('Data exported successfully!');
101+
} catch (error) {
102+
console.error('Error during bulk export:', error);
103+
this.notificationsService.showError('Failed to export data. Please try again.');
104+
} finally {
105+
this.isBulkExportLoading = false;
106+
}
107+
}
108+
109+
private downloadJsonFile(data: any, filename: string): void {
110+
const jsonString = JSON.stringify(data, null, 2);
111+
const blob = new Blob([jsonString], { type: 'application/json' });
112+
const url = URL.createObjectURL(blob);
113+
const link = document.createElement('a');
114+
115+
link.href = url;
116+
link.download = filename;
117+
document.body.appendChild(link);
118+
link.click();
119+
120+
document.body.removeChild(link);
121+
URL.revokeObjectURL(url);
122+
}
123+
87124
public async deleteUser(): Promise<void> {
88125
if (this.confirmDeleteControl.valid) {
89126
this.isLoading = true;

src/app/shared/services/firebase-functions/firebase-functions.service.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ import { UserStore } from '~store/user.store';
1111
})
1212
export class FirebaseFunctionsService {
1313
private _batchDelete: HttpsCallable;
14+
private _bulkExport: HttpsCallable;
1415
private _recursiveDelete: HttpsCallable;
1516

1617
constructor(
1718
private functions: Functions,
1819
private userStore: UserStore,
1920
) {
2021
this._batchDelete = httpsCallable(this.functions, 'batchDelete');
22+
this._bulkExport = httpsCallable(this.functions, 'bulkExport');
2123
this._recursiveDelete = httpsCallable(this.functions, 'recursiveDelete');
2224
}
2325

@@ -32,6 +34,13 @@ export class FirebaseFunctionsService {
3234
);
3335
}
3436

37+
public async bulkExport(): Promise<any> {
38+
return await this._bulkExport().catch((error) => {
39+
console.error('Error during bulk export:', error);
40+
throw error;
41+
});
42+
}
43+
3544
public async recursiveDelete(path: string, refType: ReferenceTypes): Promise<any> {
3645
await this._recursiveDelete({ path, refType }).catch((error) => {
3746
throw error;

0 commit comments

Comments
 (0)