diff --git a/CHANGELOG.md b/CHANGELOG.md index ea4c69ab6..19543b158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Added an accounts tab to the position detail dialog + ## 2.52.0 - 2024-02-16 ### Added diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts index 141e24a19..6955785f2 100644 --- a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts @@ -5,9 +5,10 @@ import { } from '@ghostfolio/common/interfaces'; import { OrderWithAccount } from '@ghostfolio/common/types'; -import { Tag } from '@prisma/client'; +import { Account, Tag } from '@prisma/client'; export interface PortfolioPositionDetail { + accounts: Account[]; averagePrice: number; dataProviderInfo: DataProviderInfo; dividendInBaseCurrency: number; diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 1156f73ad..68fce7977 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -657,6 +657,7 @@ export class PortfolioService { if (orders.length <= 0) { return { tags, + accounts: [], averagePrice: undefined, dataProviderInfo: undefined, dividendInBaseCurrency: undefined, @@ -739,6 +740,13 @@ export class PortfolioService { transactionCount } = position; + const accounts: PortfolioPositionDetail['accounts'] = uniqBy( + orders, + 'Account.id' + ).map(({ Account }) => { + return Account; + }); + const dividendInBaseCurrency = getSum( orders .filter(({ type }) => { @@ -812,6 +820,7 @@ export class PortfolioService { } return { + accounts, firstBuyDate, marketPrice, maxPrice, @@ -894,6 +903,7 @@ export class PortfolioService { orders, SymbolProfile, tags, + accounts: [], averagePrice: 0, dataProviderInfo: undefined, dividendInBaseCurrency: 0, diff --git a/apps/client/src/app/components/accounts-table/accounts-table.component.html b/apps/client/src/app/components/accounts-table/accounts-table.component.html index 199628a94..47473d303 100644 --- a/apps/client/src/app/components/accounts-table/accounts-table.component.html +++ b/apps/client/src/app/components/accounts-table/accounts-table.component.html @@ -277,14 +277,16 @@ diff --git a/apps/client/src/app/components/accounts-table/accounts-table.component.ts b/apps/client/src/app/components/accounts-table/accounts-table.component.ts index 81333ef2d..d7c948adf 100644 --- a/apps/client/src/app/components/accounts-table/accounts-table.component.ts +++ b/apps/client/src/app/components/accounts-table/accounts-table.component.ts @@ -26,8 +26,14 @@ export class AccountsTableComponent implements OnChanges, OnDestroy, OnInit { @Input() accounts: AccountModel[]; @Input() baseCurrency: string; @Input() deviceType: string; + @Input() hasPermissionToOpenDetails = true; @Input() locale: string; @Input() showActions: boolean; + @Input() showBalance = true; + @Input() showFooter = true; + @Input() showTransactions = true; + @Input() showValue = true; + @Input() showValueInBaseCurrency = true; @Input() totalBalanceInBaseCurrency: number; @Input() totalValueInBaseCurrency: number; @Input() transactionCount: number; @@ -51,17 +57,27 @@ export class AccountsTableComponent implements OnChanges, OnDestroy, OnInit { public ngOnInit() {} public ngOnChanges() { - this.displayedColumns = [ - 'status', - 'account', - 'platform', - 'transactions', - 'balance', - 'value', - 'currency', - 'valueInBaseCurrency', - 'comment' - ]; + this.displayedColumns = ['status', 'account', 'platform']; + + if (this.showTransactions) { + this.displayedColumns.push('transactions'); + } + + if (this.showBalance) { + this.displayedColumns.push('balance'); + } + + if (this.showValue) { + this.displayedColumns.push('value'); + } + + this.displayedColumns.push('currency'); + + if (this.showValueInBaseCurrency) { + this.displayedColumns.push('valueInBaseCurrency'); + } + + this.displayedColumns.push('comment'); if (this.showActions) { this.displayedColumns.push('actions'); @@ -89,9 +105,11 @@ export class AccountsTableComponent implements OnChanges, OnDestroy, OnInit { } public onOpenAccountDetailDialog(accountId: string) { - this.router.navigate([], { - queryParams: { accountId, accountDetailDialog: true } - }); + if (this.hasPermissionToOpenDetails) { + this.router.navigate([], { + queryParams: { accountId, accountDetailDialog: true } + }); + } } public onOpenComment(aComment: string) { 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 e07673878..557d15b0a 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 @@ -19,9 +19,9 @@ import { OnInit } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { Sort, SortDirection } from '@angular/material/sort'; +import { SortDirection } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; -import { Tag } from '@prisma/client'; +import { Account, Tag } from '@prisma/client'; import { format, isSameMonth, isToday, parseISO } from 'date-fns'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -36,6 +36,7 @@ import { PositionDetailDialogParams } from './interfaces/interfaces'; styleUrls: ['./position-detail-dialog.component.scss'] }) export class PositionDetailDialog implements OnDestroy, OnInit { + public accounts: Account[]; public activities: OrderWithAccount[]; public assetClass: string; public assetSubClass: string; @@ -92,6 +93,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe( ({ + accounts, averagePrice, dataProviderInfo, dividendInBaseCurrency, @@ -113,6 +115,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { transactionCount, value }) => { + this.accounts = accounts; this.activities = orders; this.averagePrice = averagePrice; this.benchmarkDataItems = []; 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 7d2421ad4..07179b801 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 @@ -241,9 +241,17 @@ -
-
-
Activities
+ + + + +
Activities
+
-
-
+ + + + +
Accounts
+
+ +
+
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 f4c03445d..675f8187b 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 @@ -1,3 +1,4 @@ +import { GfAccountsTableModule } from '@ghostfolio/client/components/accounts-table/accounts-table.module'; import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module'; @@ -11,6 +12,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatChipsModule } from '@angular/material/chips'; import { MatDialogModule } from '@angular/material/dialog'; +import { MatTabsModule } from '@angular/material/tabs'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { PositionDetailDialog } from './position-detail-dialog.component'; @@ -19,6 +21,7 @@ import { PositionDetailDialog } from './position-detail-dialog.component'; declarations: [PositionDetailDialog], imports: [ CommonModule, + GfAccountsTableModule, GfActivitiesTableModule, GfDataProviderCreditsModule, GfDialogFooterModule, @@ -29,6 +32,7 @@ import { PositionDetailDialog } from './position-detail-dialog.component'; MatButtonModule, MatChipsModule, MatDialogModule, + MatTabsModule, NgxSkeletonLoaderModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA] diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html index d4df4dd18..4dc637aa8 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -128,7 +128,6 @@ [pageSize]="maxSafeInteger" [showActions]="false" [showCheckbox]="true" - [showFooter]="false" [showSymbolColumn]="false" [sortColumn]="sortColumn" [sortDirection]="sortDirection" diff --git a/libs/ui/src/lib/activities-table/activities-table.component.ts b/libs/ui/src/lib/activities-table/activities-table.component.ts index 7845611c9..760737036 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.ts @@ -45,7 +45,6 @@ export class ActivitiesTableComponent @Input() pageSize = DEFAULT_PAGE_SIZE; @Input() showActions = true; @Input() showCheckbox = false; - @Input() showFooter = true; @Input() showNameColumn = true; @Input() sortColumn: string; @Input() sortDirection: SortDirection;