Feature/add accounts tab to position detail dialog (#3012)
* Add accounts tab to position detail dialog * Update changelog
This commit is contained in:
parent
572dcf075a
commit
2518a8fd9d
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -277,14 +277,16 @@
|
||||
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
|
||||
<tr
|
||||
*matRowDef="let row; columns: displayedColumns"
|
||||
class="cursor-pointer"
|
||||
mat-row
|
||||
[ngClass]="{
|
||||
'cursor-pointer': hasPermissionToOpenDetails
|
||||
}"
|
||||
(click)="onOpenAccountDetailDialog(row.id)"
|
||||
></tr>
|
||||
<tr
|
||||
*matFooterRowDef="displayedColumns"
|
||||
mat-footer-row
|
||||
[ngClass]="{ 'd-none': isLoading }"
|
||||
[ngClass]="{ 'd-none': isLoading || !showFooter }"
|
||||
></tr>
|
||||
</table>
|
||||
|
||||
|
@ -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,10 +105,12 @@ export class AccountsTableComponent implements OnChanges, OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
public onOpenAccountDetailDialog(accountId: string) {
|
||||
if (this.hasPermissionToOpenDetails) {
|
||||
this.router.navigate([], {
|
||||
queryParams: { accountId, accountDetailDialog: true }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public onOpenComment(aComment: string) {
|
||||
alert(aComment);
|
||||
|
@ -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 = [];
|
||||
|
@ -241,9 +241,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" [ngClass]="{ 'd-none': !activities?.length }">
|
||||
<div class="col mb-3">
|
||||
<div class="h5 mb-0" i18n>Activities</div>
|
||||
<mat-tab-group
|
||||
animationDuration="0"
|
||||
class="mb-3"
|
||||
[mat-stretch-tabs]="false"
|
||||
[ngClass]="{ 'd-none': !activities?.length }"
|
||||
>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<ion-icon name="swap-vertical-outline" />
|
||||
<div class="d-none d-sm-block ml-2" i18n>Activities</div>
|
||||
</ng-template>
|
||||
<gf-activities-table
|
||||
[baseCurrency]="data.baseCurrency"
|
||||
[dataSource]="dataSource"
|
||||
@ -261,8 +269,26 @@
|
||||
[totalItems]="totalItems"
|
||||
(export)="onExport()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<ion-icon name="wallet-outline" />
|
||||
<div class="d-none d-sm-block ml-2" i18n>Accounts</div>
|
||||
</ng-template>
|
||||
<gf-accounts-table
|
||||
[accounts]="accounts"
|
||||
[baseCurrency]="user?.settings?.baseCurrency"
|
||||
[deviceType]="data.deviceType"
|
||||
[hasPermissionToOpenDetails]="false"
|
||||
[locale]="user?.settings?.locale"
|
||||
[showBalance]="false"
|
||||
[showFooter]="false"
|
||||
[showTransactions]="false"
|
||||
[showValue]="false"
|
||||
[showValueInBaseCurrency]="false"
|
||||
/>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
||||
<div *ngIf="tags?.length > 0" class="row">
|
||||
<div class="col">
|
||||
|
@ -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]
|
||||
|
@ -128,7 +128,6 @@
|
||||
[pageSize]="maxSafeInteger"
|
||||
[showActions]="false"
|
||||
[showCheckbox]="true"
|
||||
[showFooter]="false"
|
||||
[showSymbolColumn]="false"
|
||||
[sortColumn]="sortColumn"
|
||||
[sortDirection]="sortDirection"
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user