Add cash balances table to account detail dialog (#2549)
* Add cash balances table to account detail dialog * Update changelog --------- Co-authored-by: Thomas <4159106+dtslvr@users.noreply.github.com>
This commit is contained in:
parent
6f4fd0826c
commit
ed4dd79c72
@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- Added a historical cash balances table to the account detail dialog
|
||||
|
||||
### Changed
|
||||
|
||||
- Respected the `withExcludedAccounts` flag in the account balance time series
|
||||
|
||||
## 2.27.1 - 2023-11-28
|
||||
|
@ -29,14 +29,15 @@ import { AccountDetailDialogParams } from './interfaces/interfaces';
|
||||
styleUrls: ['./account-detail-dialog.component.scss']
|
||||
})
|
||||
export class AccountDetailDialog implements OnDestroy, OnInit {
|
||||
public activities: OrderWithAccount[];
|
||||
public balance: number;
|
||||
public currency: string;
|
||||
public equity: number;
|
||||
public hasImpersonationId: boolean;
|
||||
public historicalDataItems: HistoricalDataItem[];
|
||||
public isLoadingActivities: boolean;
|
||||
public isLoadingChart: boolean;
|
||||
public name: string;
|
||||
public orders: OrderWithAccount[];
|
||||
public platformName: string;
|
||||
public transactionCount: number;
|
||||
public user: User;
|
||||
@ -64,6 +65,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.isLoadingActivities = true;
|
||||
this.isLoadingChart = true;
|
||||
|
||||
this.dataService
|
||||
@ -103,7 +105,9 @@ export class AccountDetailDialog implements OnDestroy, OnInit {
|
||||
})
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe(({ activities }) => {
|
||||
this.orders = activities;
|
||||
this.activities = activities;
|
||||
|
||||
this.isLoadingActivities = false;
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
@ -153,8 +157,8 @@ export class AccountDetailDialog implements OnDestroy, OnInit {
|
||||
public onExport() {
|
||||
this.dataService
|
||||
.fetchExport(
|
||||
this.orders.map((order) => {
|
||||
return order.id;
|
||||
this.activities.map(({ id }) => {
|
||||
return id;
|
||||
})
|
||||
)
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
|
@ -31,7 +31,7 @@
|
||||
></gf-investment-chart>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="mb-3 row">
|
||||
<div class="col-6 mb-3">
|
||||
<gf-value
|
||||
i18n
|
||||
@ -64,11 +64,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" [ngClass]="{ 'd-none': !orders?.length }">
|
||||
<div class="col mb-3">
|
||||
<div class="h5 mb-0" i18n>Activities</div>
|
||||
<mat-tab-group
|
||||
animationDuration="0"
|
||||
[mat-stretch-tabs]="false"
|
||||
[ngClass]="{ 'd-none': isLoadingActivities }"
|
||||
>
|
||||
<mat-tab>
|
||||
<ng-template i18n mat-tab-label>Activities</ng-template>
|
||||
<gf-activities-table
|
||||
[activities]="orders"
|
||||
[activities]="activities"
|
||||
[baseCurrency]="user?.settings?.baseCurrency"
|
||||
[deviceType]="data.deviceType"
|
||||
[hasPermissionToCreateActivity]="false"
|
||||
@ -79,8 +83,15 @@
|
||||
[showActions]="false"
|
||||
(export)="onExport()"
|
||||
></gf-activities-table>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab>
|
||||
<ng-template i18n mat-tab-label>Cash Balances</ng-template>
|
||||
<gf-account-balances
|
||||
[accountId]="data.accountId"
|
||||
[locale]="user?.settings?.locale"
|
||||
></gf-account-balances>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -2,9 +2,11 @@ import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
|
||||
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
|
||||
import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module';
|
||||
import { GfAccountBalancesModule } from '@ghostfolio/ui/account-balances/account-balances.module';
|
||||
import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
@ -15,6 +17,7 @@ import { AccountDetailDialog } from './account-detail-dialog.component';
|
||||
declarations: [AccountDetailDialog],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfAccountBalancesModule,
|
||||
GfActivitiesTableModule,
|
||||
GfDialogFooterModule,
|
||||
GfDialogHeaderModule,
|
||||
@ -22,6 +25,7 @@ import { AccountDetailDialog } from './account-detail-dialog.component';
|
||||
GfValueModule,
|
||||
MatButtonModule,
|
||||
MatDialogModule,
|
||||
MatTabsModule,
|
||||
NgxSkeletonLoaderModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="container">
|
||||
<div class="row mb-3">
|
||||
<div class="mb-3 row">
|
||||
<div class="col">
|
||||
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Activities</h1>
|
||||
<gf-activities-table
|
||||
|
@ -18,6 +18,7 @@ import { PropertyDto } from '@ghostfolio/api/services/property/property.dto';
|
||||
import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
||||
import {
|
||||
Access,
|
||||
AccountBalancesResponse,
|
||||
Accounts,
|
||||
BenchmarkMarketDataDetails,
|
||||
BenchmarkResponse,
|
||||
@ -137,6 +138,12 @@ export class DataService {
|
||||
return this.http.get<AccountWithValue>(`/api/v1/account/${aAccountId}`);
|
||||
}
|
||||
|
||||
public fetchAccountBalances(aAccountId: string) {
|
||||
return this.http.get<AccountBalancesResponse>(
|
||||
`/api/v1/account/${aAccountId}/balances`
|
||||
);
|
||||
}
|
||||
|
||||
public fetchAccounts() {
|
||||
return this.http.get<Accounts>('/api/v1/account');
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
<table
|
||||
class="gf-table w-100"
|
||||
mat-table
|
||||
matSort
|
||||
matSortActive="date"
|
||||
matSortDirection="desc"
|
||||
[dataSource]="dataSource"
|
||||
>
|
||||
<ng-container matColumnDef="date">
|
||||
<th *matHeaderCellDef class="px-2" mat-header-cell mat-sort-header>
|
||||
<ng-container i18n>Date</ng-container>
|
||||
</th>
|
||||
<td *matCellDef="let element" class="px-2" mat-cell>
|
||||
<gf-value [isDate]="true" [locale]="locale" [value]="element?.date" />
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="value">
|
||||
<th *matHeaderCellDef class="px-2 text-right" mat-header-cell>
|
||||
<ng-container i18n>Value</ng-container>
|
||||
</th>
|
||||
<td *matCellDef="let element" class="px-2" mat-cell>
|
||||
<div class="d-flex justify-content-end">
|
||||
<gf-value
|
||||
[isCurrency]="true"
|
||||
[locale]="locale"
|
||||
[unit]="element?.Account?.currency"
|
||||
[value]="element?.value"
|
||||
></gf-value>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
|
||||
<tr *matRowDef="let row; columns: displayedColumns" mat-row></tr>
|
||||
</table>
|
@ -0,0 +1,5 @@
|
||||
@import 'apps/client/src/styles/ghostfolio-style';
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { AccountBalancesResponse } from '@ghostfolio/common/interfaces';
|
||||
import { get } from 'lodash';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
selector: 'gf-account-balances',
|
||||
styleUrls: ['./account-balances.component.scss'],
|
||||
templateUrl: './account-balances.component.html'
|
||||
})
|
||||
export class AccountBalancesComponent implements OnDestroy, OnInit {
|
||||
@Input() accountId: string;
|
||||
@Input() locale: string;
|
||||
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
|
||||
public dataSource: MatTableDataSource<
|
||||
AccountBalancesResponse['balances'][0]
|
||||
> = new MatTableDataSource();
|
||||
public displayedColumns: string[] = ['date', 'value'];
|
||||
|
||||
private unsubscribeSubject = new Subject<void>();
|
||||
|
||||
public constructor(
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
private dataService: DataService
|
||||
) {}
|
||||
|
||||
public ngOnInit() {
|
||||
this.fetchBalances();
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
this.unsubscribeSubject.next();
|
||||
this.unsubscribeSubject.complete();
|
||||
}
|
||||
|
||||
private fetchBalances() {
|
||||
this.dataService
|
||||
.fetchAccountBalances(this.accountId)
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe(({ balances }) => {
|
||||
this.dataSource = new MatTableDataSource(balances);
|
||||
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.sortingDataAccessor = get;
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
}
|
15
libs/ui/src/lib/account-balances/account-balances.module.ts
Normal file
15
libs/ui/src/lib/account-balances/account-balances.module.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
|
||||
import { AccountBalancesComponent } from './account-balances.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AccountBalancesComponent],
|
||||
exports: [AccountBalancesComponent],
|
||||
imports: [CommonModule, GfValueModule, MatSortModule, MatTableModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class GfAccountBalancesModule {}
|
Loading…
x
Reference in New Issue
Block a user