Feature/fix export in lazy-loaded activities table (#2939)

* Fix export in lazy-loaded activities table

* Update changelog

---------

Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
This commit is contained in:
Arshad Jamal 2024-01-30 00:07:09 +05:30 committed by GitHub
parent 6dcb0d8583
commit e82dcc8ace
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 45 additions and 10 deletions

View File

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- Fixed the export in the lazy-loaded activities table on the portfolio activities page (experimental)
## 2.46.0 - 2024-01-28 ## 2.46.0 - 2024-01-28
### Added ### Added

View File

@ -1,4 +1,5 @@
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { ApiService } from '@ghostfolio/api/services/api/api.service';
import { Export } from '@ghostfolio/common/interfaces'; import { Export } from '@ghostfolio/common/interfaces';
import type { RequestWithUser } from '@ghostfolio/common/types'; import type { RequestWithUser } from '@ghostfolio/common/types';
import { Controller, Get, Inject, Query, UseGuards } from '@nestjs/common'; import { Controller, Get, Inject, Query, UseGuards } from '@nestjs/common';
@ -10,6 +11,7 @@ import { ExportService } from './export.service';
@Controller('export') @Controller('export')
export class ExportController { export class ExportController {
public constructor( public constructor(
private readonly apiService: ApiService,
private readonly exportService: ExportService, private readonly exportService: ExportService,
@Inject(REQUEST) private readonly request: RequestWithUser @Inject(REQUEST) private readonly request: RequestWithUser
) {} ) {}
@ -17,10 +19,20 @@ export class ExportController {
@Get() @Get()
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async export( public async export(
@Query('activityIds') activityIds?: string[] @Query('accounts') filterByAccounts?: string,
@Query('activityIds') activityIds?: string[],
@Query('assetClasses') filterByAssetClasses?: string,
@Query('tags') filterByTags?: string
): Promise<Export> { ): Promise<Export> {
const filters = this.apiService.buildFiltersFromQueryParams({
filterByAccounts,
filterByAssetClasses,
filterByTags
});
return this.exportService.export({ return this.exportService.export({
activityIds, activityIds,
filters,
userCurrency: this.request.user.Settings.settings.baseCurrency, userCurrency: this.request.user.Settings.settings.baseCurrency,
userId: this.request.user.id userId: this.request.user.id
}); });

View File

@ -1,6 +1,7 @@
import { AccountModule } from '@ghostfolio/api/app/account/account.module'; import { AccountModule } from '@ghostfolio/api/app/account/account.module';
import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { OrderModule } from '@ghostfolio/api/app/order/order.module';
import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module';
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module';
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
@ -12,6 +13,7 @@ import { ExportService } from './export.service';
@Module({ @Module({
imports: [ imports: [
AccountModule, AccountModule,
ApiModule,
ConfigurationModule, ConfigurationModule,
DataGatheringModule, DataGatheringModule,
DataProviderModule, DataProviderModule,

View File

@ -1,7 +1,7 @@
import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service';
import { OrderService } from '@ghostfolio/api/app/order/order.service'; import { OrderService } from '@ghostfolio/api/app/order/order.service';
import { environment } from '@ghostfolio/api/environments/environment'; import { environment } from '@ghostfolio/api/environments/environment';
import { Export } from '@ghostfolio/common/interfaces'; import { Filter, Export } from '@ghostfolio/common/interfaces';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
@Injectable() @Injectable()
@ -13,10 +13,12 @@ export class ExportService {
public async export({ public async export({
activityIds, activityIds,
filters,
userCurrency, userCurrency,
userId userId
}: { }: {
activityIds?: string[]; activityIds?: string[];
filters?: Filter[];
userCurrency: string; userCurrency: string;
userId: string; userId: string;
}): Promise<Export> { }): Promise<Export> {
@ -42,6 +44,7 @@ export class ExportService {
); );
let { activities } = await this.orderService.getOrders({ let { activities } = await this.orderService.getOrders({
filters,
userCurrency, userCurrency,
userId, userId,
includeDrafts: true, includeDrafts: true,

View File

@ -178,7 +178,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit {
} }
this.dataService this.dataService
.fetchExport(activityIds) .fetchExport({ activityIds })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe((data) => { .subscribe((data) => {
downloadAsFile({ downloadAsFile({

View File

@ -281,7 +281,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
} }
this.dataService this.dataService
.fetchExport(activityIds) .fetchExport({ activityIds })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe((data) => { .subscribe((data) => {
downloadAsFile({ downloadAsFile({

View File

@ -199,8 +199,14 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit {
} }
public onExport(activityIds?: string[]) { public onExport(activityIds?: string[]) {
let fetchExportParams: any = { activityIds };
if (!activityIds) {
fetchExportParams = { filters: this.userService.getFilters() };
}
this.dataService this.dataService
.fetchExport(activityIds) .fetchExport(fetchExportParams)
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe((data) => { .subscribe((data) => {
for (const activity of data.activities) { for (const activity of data.activities) {
@ -220,7 +226,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit {
public onExportDrafts(activityIds?: string[]) { public onExportDrafts(activityIds?: string[]) {
this.dataService this.dataService
.fetchExport(activityIds) .fetchExport({ activityIds })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe((data) => { .subscribe((data) => {
downloadAsFile({ downloadAsFile({

View File

@ -20,7 +20,7 @@
(activityToClone)="onCloneActivity($event)" (activityToClone)="onCloneActivity($event)"
(activityToUpdate)="onUpdateActivity($event)" (activityToUpdate)="onUpdateActivity($event)"
(deleteAllActivities)="onDeleteAllActivities()" (deleteAllActivities)="onDeleteAllActivities()"
(export)="onExport($event)" (export)="onExport()"
(exportDrafts)="onExportDrafts($event)" (exportDrafts)="onExportDrafts($event)"
(import)="onImport()" (import)="onImport()"
(importDividends)="onImportDividends()" (importDividends)="onImportDividends()"

View File

@ -279,8 +279,14 @@ export class DataService {
return this.http.get<BenchmarkResponse>('/api/v1/benchmark'); return this.http.get<BenchmarkResponse>('/api/v1/benchmark');
} }
public fetchExport(activityIds?: string[]) { public fetchExport({
let params = new HttpParams(); activityIds,
filters
}: {
activityIds?: string[];
filters?: Filter[];
} = {}) {
let params = this.buildFiltersAsQueryParams({ filters });
if (activityIds) { if (activityIds) {
params = params.append('activityIds', activityIds.join(',')); params = params.append('activityIds', activityIds.join(','));

View File

@ -55,7 +55,7 @@ export class ActivitiesTableLazyComponent
@Output() activityToClone = new EventEmitter<OrderWithAccount>(); @Output() activityToClone = new EventEmitter<OrderWithAccount>();
@Output() activityToUpdate = new EventEmitter<OrderWithAccount>(); @Output() activityToUpdate = new EventEmitter<OrderWithAccount>();
@Output() deleteAllActivities = new EventEmitter<void>(); @Output() deleteAllActivities = new EventEmitter<void>();
@Output() export = new EventEmitter<string[]>(); @Output() export = new EventEmitter<void>();
@Output() exportDrafts = new EventEmitter<string[]>(); @Output() exportDrafts = new EventEmitter<string[]>();
@Output() import = new EventEmitter<void>(); @Output() import = new EventEmitter<void>();
@Output() importDividends = new EventEmitter<UniqueAsset>(); @Output() importDividends = new EventEmitter<UniqueAsset>();