From 4547c5da1de87aedbc94fa472f7f2784f0a6eb85 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 16 Dec 2023 17:10:19 +0100 Subject: [PATCH] Feature/add lazy loaded activities table to position detail dialog (#2753) * Add lazy-loaded activities table * Update changelog --- CHANGELOG.md | 1 + .../position-detail-dialog.component.ts | 48 +++++++++++++++---- .../position-detail-dialog.html | 25 ++++++++-- .../position-detail-dialog.module.ts | 2 + .../activities-table-lazy.component.html | 1 + .../activities-table-lazy.component.ts | 1 + 6 files changed, 66 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4383a828..e3210ea52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Introduced the lazy-loaded activities table to the position detail dialog (experimental) - Improved the font weight in the value component - Improved the language localization for Türkçe (`tr`) - Upgraded to _Inter_ 4 font family diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts index bc68cf231..053d1d305 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts @@ -7,12 +7,16 @@ import { OnInit } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Sort, SortDirection } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; import { DataService } from '@ghostfolio/client/services/data.service'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; import { DATE_FORMAT, downloadAsFile } from '@ghostfolio/common/helper'; import { DataProviderInfo, EnhancedSymbolProfile, - LineChartItem + LineChartItem, + User } from '@ghostfolio/common/interfaces'; import { OrderWithAccount } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; @@ -31,6 +35,7 @@ import { PositionDetailDialogParams } from './interfaces/interfaces'; styleUrls: ['./position-detail-dialog.component.scss'] }) export class PositionDetailDialog implements OnDestroy, OnInit { + public activities: OrderWithAccount[]; public assetClass: string; public assetSubClass: string; public averagePrice: number; @@ -39,6 +44,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { [code: string]: { name: string; value: number }; }; public dataProviderInfo: DataProviderInfo; + public dataSource: MatTableDataSource; public dividendInBaseCurrency: number; public feeInBaseCurrency: number; public firstBuyDate: string; @@ -51,16 +57,19 @@ export class PositionDetailDialog implements OnDestroy, OnInit { public minPrice: number; public netPerformance: number; public netPerformancePercent: number; - public orders: OrderWithAccount[]; public quantity: number; public quantityPrecision = 2; public reportDataGlitchMail: string; public sectors: { [name: string]: { name: string; value: number }; }; + public sortColumn = 'date'; + public sortDirection: SortDirection = 'desc'; public SymbolProfile: EnhancedSymbolProfile; public tags: Tag[]; + public totalItems: number; public transactionCount: number; + public user: User; public value: number; private unsubscribeSubject = new Subject(); @@ -69,7 +78,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: PositionDetailDialogParams + @Inject(MAT_DIALOG_DATA) public data: PositionDetailDialogParams, + private userService: UserService ) {} public ngOnInit(): void { @@ -102,10 +112,12 @@ export class PositionDetailDialog implements OnDestroy, OnInit { transactionCount, value }) => { + this.activities = orders; this.averagePrice = averagePrice; this.benchmarkDataItems = []; this.countries = {}; this.dataProviderInfo = dataProviderInfo; + this.dataSource = new MatTableDataSource(orders.reverse()); this.dividendInBaseCurrency = dividendInBaseCurrency; this.feeInBaseCurrency = feeInBaseCurrency; this.firstBuyDate = firstBuyDate; @@ -130,7 +142,6 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.minPrice = minPrice; this.netPerformance = netPerformance; this.netPerformancePercent = netPerformancePercent; - this.orders = orders; this.quantity = quantity; this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=Ghostfolio Data Glitch Report&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${SymbolProfile?.symbol}%0DData Source: ${SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`; this.sectors = {}; @@ -142,6 +153,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { }; }); this.transactionCount = transactionCount; + this.totalItems = transactionCount; this.value = value; if (SymbolProfile?.assetClass) { @@ -239,6 +251,16 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); } ); + + this.userService.stateChanged + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((state) => { + if (state?.user) { + this.user = state.user; + + this.changeDetectorRef.markForCheck(); + } + }); } public onClose(): void { @@ -246,12 +268,20 @@ export class PositionDetailDialog implements OnDestroy, OnInit { } public onExport() { + let activityIds = []; + + if (this.user?.settings?.isExperimentalFeatures === true) { + activityIds = this.dataSource.data.map(({ id }) => { + return id; + }); + } else { + activityIds = this.activities.map(({ id }) => { + return id; + }); + } + this.dataService - .fetchExport( - this.orders.map((order) => { - return order.id; - }) - ) + .fetchExport(activityIds) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((data) => { downloadAsFile({ diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html index 8d0f62ed9..f7b9b8a80 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html @@ -246,11 +246,30 @@ -
+
Activities
+
diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.module.ts b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.module.ts index 4c9a4a923..46ae87f66 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.module.ts +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.module.ts @@ -5,6 +5,7 @@ import { MatChipsModule } from '@angular/material/chips'; import { MatDialogModule } from '@angular/material/dialog'; import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; +import { GfActivitiesTableLazyModule } from '@ghostfolio/ui/activities-table-lazy/activities-table-lazy.module'; import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module'; import { GfDataProviderCreditsModule } from '@ghostfolio/ui/data-provider-credits/data-provider-credits.module'; import { GfLineChartModule } from '@ghostfolio/ui/line-chart/line-chart.module'; @@ -19,6 +20,7 @@ import { PositionDetailDialog } from './position-detail-dialog.component'; imports: [ CommonModule, GfActivitiesTableModule, + GfActivitiesTableLazyModule, GfDataProviderCreditsModule, GfDialogFooterModule, GfDialogHeaderModule, diff --git a/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.html b/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.html index 1173c4854..460f218e1 100644 --- a/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.html +++ b/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.html @@ -72,6 +72,7 @@ [dataSource]="dataSource" [matSortActive]="sortColumn" [matSortDirection]="sortDirection" + [matSortDisabled]="sortDisabled" > diff --git a/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts b/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts index caab993e0..950df149b 100644 --- a/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts +++ b/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts @@ -48,6 +48,7 @@ export class ActivitiesTableLazyComponent @Input() showNameColumn = true; @Input() sortColumn: string; @Input() sortDirection: SortDirection; + @Input() sortDisabled = false; @Input() totalItems = Number.MAX_SAFE_INTEGER; @Output() activityDeleted = new EventEmitter();