Browse Source
Task/improve export functionality (#7499)
* Improve export functionality
* Update changelog
pull/7500/head^2
Thomas Kaul
1 week ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with
33 additions and
14 deletions
-
CHANGELOG.md
-
apps/api/src/app/export/export.service.ts
-
apps/client/src/app/components/user-account-settings/user-account-settings.component.ts
-
apps/client/src/app/pages/portfolio/activities/activities-page.component.ts
-
libs/ui/src/lib/services/data.service.ts
|
|
@ -9,9 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 |
|
|
|
|
|
|
|
|
### Changed |
|
|
### Changed |
|
|
|
|
|
|
|
|
|
|
|
- Harmonized the data format of the export functionality |
|
|
- Improved the language localization for German (`de`) |
|
|
- Improved the language localization for German (`de`) |
|
|
- Upgraded `prisma` from version `7.8.0` to `7.9.1` |
|
|
- Upgraded `prisma` from version `7.8.0` to `7.9.1` |
|
|
|
|
|
|
|
|
|
|
|
### Fixed |
|
|
|
|
|
|
|
|
|
|
|
- Fixed the export functionality to only include the accounts of the exported activities if a filter is applied |
|
|
|
|
|
|
|
|
## 3.38.0 - 2026-07-31 |
|
|
## 3.38.0 - 2026-07-31 |
|
|
|
|
|
|
|
|
### Added |
|
|
### Added |
|
|
|
|
|
@ -73,6 +73,13 @@ export class ExportService { |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const isFilteredExport = |
|
|
|
|
|
activityIds?.length > 0 || |
|
|
|
|
|
activityTypes?.length > 0 || |
|
|
|
|
|
filters?.length > 0 || |
|
|
|
|
|
!!endDate || |
|
|
|
|
|
!!startDate; |
|
|
|
|
|
|
|
|
const accounts = ( |
|
|
const accounts = ( |
|
|
await this.accountService.accounts({ |
|
|
await this.accountService.accounts({ |
|
|
where, |
|
|
where, |
|
|
@ -87,7 +94,7 @@ export class ExportService { |
|
|
}) |
|
|
}) |
|
|
) |
|
|
) |
|
|
.filter(({ id }) => { |
|
|
.filter(({ id }) => { |
|
|
return activityIds?.length > 0 |
|
|
return isFilteredExport |
|
|
? activities.some(({ accountId }) => { |
|
|
? activities.some(({ accountId }) => { |
|
|
return accountId === id; |
|
|
return accountId === id; |
|
|
}) |
|
|
}) |
|
|
|
|
|
@ -266,10 +266,6 @@ export class GfUserAccountSettingsComponent implements OnInit { |
|
|
.fetchExport() |
|
|
.fetchExport() |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe((data) => { |
|
|
.subscribe((data) => { |
|
|
for (const activity of data.activities) { |
|
|
|
|
|
delete (activity as Omit<typeof activity, 'id'> & { id?: string }).id; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
downloadAsFile({ |
|
|
downloadAsFile({ |
|
|
content: data, |
|
|
content: data, |
|
|
fileName: `ghostfolio-export-${format( |
|
|
fileName: `ghostfolio-export-${format( |
|
|
|
|
|
@ -177,10 +177,6 @@ export class GfActivitiesPageComponent implements OnInit { |
|
|
.fetchExport(fetchExportParams) |
|
|
.fetchExport(fetchExportParams) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe((data) => { |
|
|
.subscribe((data) => { |
|
|
for (const activity of data.activities) { |
|
|
|
|
|
delete (activity as Omit<typeof activity, 'id'> & { id?: string }).id; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
downloadAsFile({ |
|
|
downloadAsFile({ |
|
|
content: data, |
|
|
content: data, |
|
|
fileName: `ghostfolio-export-${format( |
|
|
fileName: `ghostfolio-export-${format( |
|
|
@ -194,7 +190,7 @@ export class GfActivitiesPageComponent implements OnInit { |
|
|
|
|
|
|
|
|
protected onExportDrafts(activityIds?: string[]) { |
|
|
protected onExportDrafts(activityIds?: string[]) { |
|
|
this.dataService |
|
|
this.dataService |
|
|
.fetchExport({ activityIds }) |
|
|
.fetchExport({ activityIds, withActivityIds: true }) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe((data) => { |
|
|
.subscribe((data) => { |
|
|
downloadAsFile({ |
|
|
downloadAsFile({ |
|
|
|
|
|
@ -476,12 +476,14 @@ export class DataService { |
|
|
activityIds, |
|
|
activityIds, |
|
|
activityTypes, |
|
|
activityTypes, |
|
|
filters, |
|
|
filters, |
|
|
range |
|
|
range, |
|
|
|
|
|
withActivityIds = false |
|
|
}: { |
|
|
}: { |
|
|
activityIds?: string[]; |
|
|
activityIds?: string[]; |
|
|
activityTypes?: string[]; |
|
|
activityTypes?: string[]; |
|
|
filters?: Filter[]; |
|
|
filters?: Filter[]; |
|
|
range?: DateRange; |
|
|
range?: DateRange; |
|
|
|
|
|
withActivityIds?: boolean; |
|
|
} = {}) { |
|
|
} = {}) { |
|
|
let params = this.buildFiltersAsQueryParams({ filters }); |
|
|
let params = this.buildFiltersAsQueryParams({ filters }); |
|
|
|
|
|
|
|
|
@ -497,9 +499,22 @@ export class DataService { |
|
|
params = params.append('range', range); |
|
|
params = params.append('range', range); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return this.http.get<ExportResponse>('/api/v1/export', { |
|
|
return this.http |
|
|
|
|
|
.get<ExportResponse>('/api/v1/export', { |
|
|
params |
|
|
params |
|
|
}); |
|
|
}) |
|
|
|
|
|
.pipe( |
|
|
|
|
|
map((exportResponse) => { |
|
|
|
|
|
if (!withActivityIds) { |
|
|
|
|
|
for (const activity of exportResponse.activities) { |
|
|
|
|
|
delete (activity as Omit<typeof activity, 'id'> & { id?: string }) |
|
|
|
|
|
.id; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return exportResponse; |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public fetchHoldingDetail({ |
|
|
public fetchHoldingDetail({ |
|
|
|