Browse Source

feat: show account balances

pull/2549/head
Sanjeev Sharma 2 years ago
committed by Thomas
parent
commit
760180ea75
  1. 91
      apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html
  2. 4
      apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts
  3. 7
      apps/client/src/app/services/data.service.ts
  4. 5
      libs/common/src/lib/interfaces/account-balance.interface.ts
  5. 2
      libs/common/src/lib/interfaces/index.ts
  6. 15
      libs/ui/src/lib/account-balances/account-balances.component.html
  7. 19
      libs/ui/src/lib/account-balances/account-balances.component.scss
  8. 46
      libs/ui/src/lib/account-balances/account-balances.component.ts
  9. 44
      libs/ui/src/lib/account-balances/account-balances.module.ts

91
apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html

@ -1,91 +1,50 @@
<gf-dialog-header <gf-dialog-header mat-dialog-title position="center" [deviceType]="data.deviceType" [title]="name"
mat-dialog-title (closeButtonClicked)="onClose()"></gf-dialog-header>
position="center"
[deviceType]="data.deviceType"
[title]="name"
(closeButtonClicked)="onClose()"
></gf-dialog-header>
<div class="flex-grow-1" mat-dialog-content> <div class="flex-grow-1" mat-dialog-content>
<div class="container p-0"> <div class="container p-0">
<div class="row"> <div class="row">
<div class="col-12 d-flex justify-content-center mb-3"> <div class="col-12 d-flex justify-content-center mb-3">
<gf-value <gf-value size="large" [isCurrency]="true" [locale]="user?.settings?.locale"
size="large" [unit]="user?.settings?.baseCurrency" [value]="valueInBaseCurrency"></gf-value>
[isCurrency]="true"
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="valueInBaseCurrency"
></gf-value>
</div> </div>
</div> </div>
<div class="chart-container mb-3"> <div class="chart-container mb-3">
<gf-investment-chart <gf-investment-chart class="h-100" [currency]="user?.settings?.baseCurrency"
class="h-100" [historicalDataItems]="historicalDataItems" [isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
[currency]="user?.settings?.baseCurrency" [isLoading]="isLoadingChart" [locale]="user?.settings?.locale"></gf-investment-chart>
[historicalDataItems]="historicalDataItems"
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
[isLoading]="isLoadingChart"
[locale]="user?.settings?.locale"
></gf-investment-chart>
</div> </div>
<div class="row"> <div class="row mb-3">
<div class="col-6 mb-3"> <div class="col-6 mb-3">
<gf-value <gf-value i18n size="medium" [isCurrency]="true" [locale]="user?.settings?.locale" [unit]="currency"
i18n [value]="balance">Cash Balance</gf-value>
size="medium"
[isCurrency]="true"
[locale]="user?.settings?.locale"
[unit]="currency"
[value]="balance"
>Cash Balance</gf-value
>
</div> </div>
<div class="col-6 mb-3"> <div class="col-6 mb-3">
<gf-value <gf-value i18n size="medium" [isCurrency]="true" [locale]="user?.settings?.locale" [unit]="currency"
i18n [value]="equity">Equity</gf-value>
size="medium"
[isCurrency]="true"
[locale]="user?.settings?.locale"
[unit]="currency"
[value]="equity"
>Equity</gf-value
>
</div> </div>
<div class="col-6 mb-3"> <div class="col-6 mb-3">
<gf-value i18n size="medium" [value]="transactionCount" <gf-value i18n size="medium" [value]="transactionCount">Activities</gf-value>
>Activities</gf-value
>
</div> </div>
<div class="col-6 mb-3"> <div class="col-6 mb-3">
<gf-value i18n size="medium" [value]="platformName">Platform</gf-value> <gf-value i18n size="medium" [value]="platformName">Platform</gf-value>
</div> </div>
</div> </div>
<div class="row" [ngClass]="{ 'd-none': !orders?.length }"> <mat-tab-group>
<div class="col mb-3"> <mat-tab label="Activities">
<div class="h5 mb-0" i18n>Activities</div> <gf-activities-table [activities]="orders" [baseCurrency]="user?.settings?.baseCurrency"
<gf-activities-table [deviceType]="data.deviceType" [hasPermissionToCreateActivity]="false"
[activities]="orders" [hasPermissionToExportActivities]="true" [hasPermissionToFilter]="false" [hasPermissionToOpenDetails]="false"
[baseCurrency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [showActions]="false" (export)="onExport()"></gf-activities-table>
[deviceType]="data.deviceType" </mat-tab>
[hasPermissionToCreateActivity]="false" <mat-tab label="Balances">
[hasPermissionToExportActivities]="true" <gf-account-balances [accountId]="data.accountId"></gf-account-balances>
[hasPermissionToFilter]="false" </mat-tab>
[hasPermissionToOpenDetails]="false" </mat-tab-group>
[locale]="user?.settings?.locale"
[showActions]="false"
(export)="onExport()"
></gf-activities-table>
</div>
</div>
</div> </div>
</div> </div>
<gf-dialog-footer <gf-dialog-footer mat-dialog-actions [deviceType]="data.deviceType" (closeButtonClicked)="onClose()"></gf-dialog-footer>
mat-dialog-actions
[deviceType]="data.deviceType"
(closeButtonClicked)="onClose()"
></gf-dialog-footer>

4
apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts

@ -2,10 +2,12 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
import { MatTabsModule } from '@angular/material/tabs';
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module'; import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module';
import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module'; import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module';
import { GfAccountBalancesModule } from '@ghostfolio/ui/account-balances/account-balances.module';
import { GfValueModule } from '@ghostfolio/ui/value'; import { GfValueModule } from '@ghostfolio/ui/value';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
@ -15,6 +17,7 @@ import { AccountDetailDialog } from './account-detail-dialog.component';
declarations: [AccountDetailDialog], declarations: [AccountDetailDialog],
imports: [ imports: [
CommonModule, CommonModule,
GfAccountBalancesModule,
GfActivitiesTableModule, GfActivitiesTableModule,
GfDialogFooterModule, GfDialogFooterModule,
GfDialogHeaderModule, GfDialogHeaderModule,
@ -22,6 +25,7 @@ import { AccountDetailDialog } from './account-detail-dialog.component';
GfValueModule, GfValueModule,
MatButtonModule, MatButtonModule,
MatDialogModule, MatDialogModule,
MatTabsModule,
NgxSkeletonLoaderModule NgxSkeletonLoaderModule
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]

7
apps/client/src/app/services/data.service.ts

@ -18,6 +18,7 @@ import { PropertyDto } from '@ghostfolio/api/services/property/property.dto';
import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { import {
Access, Access,
AccountBalancesResponse,
Accounts, Accounts,
BenchmarkMarketDataDetails, BenchmarkMarketDataDetails,
BenchmarkResponse, BenchmarkResponse,
@ -141,6 +142,12 @@ export class DataService {
return this.http.get<Accounts>('/api/v1/account'); return this.http.get<Accounts>('/api/v1/account');
} }
public fetchAccountBalances(accountId: string) {
return this.http.get<AccountBalancesResponse>(
`/api/v1/account/${accountId}/balances`
);
}
public fetchActivities({ public fetchActivities({
filters filters
}: { }: {

5
libs/common/src/lib/interfaces/account-balance.interface.ts

@ -0,0 +1,5 @@
export interface AccountBalance {
date: Date;
id: string;
value: number;
}

2
libs/common/src/lib/interfaces/index.ts

@ -1,5 +1,6 @@
import type { Access } from './access.interface'; import type { Access } from './access.interface';
import type { Accounts } from './accounts.interface'; import type { Accounts } from './accounts.interface';
import type { AccountBalance } from './account-balance.interface';
import type { AdminData } from './admin-data.interface'; import type { AdminData } from './admin-data.interface';
import type { AdminJobs } from './admin-jobs.interface'; import type { AdminJobs } from './admin-jobs.interface';
import type { AdminMarketDataDetails } from './admin-market-data-details.interface'; import type { AdminMarketDataDetails } from './admin-market-data-details.interface';
@ -51,6 +52,7 @@ import type { User } from './user.interface';
export { export {
Access, Access,
AccountBalance,
AccountBalancesResponse, AccountBalancesResponse,
Accounts, Accounts,
AdminData, AdminData,

15
libs/ui/src/lib/account-balances/account-balances.component.html

@ -0,0 +1,15 @@
<table mat-table [dataSource]="balances" class="mat-elevation-z8">
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef> Date </th>
<td mat-cell *matCellDef="let balance"> {{balance.date}} </td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef> Value </th>
<td mat-cell *matCellDef="let balance"> {{balance.value}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

19
libs/ui/src/lib/account-balances/account-balances.component.scss

@ -0,0 +1,19 @@
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;
.activities {
overflow-x: auto;
.mat-mdc-table {
th {
::ng-deep {
.mat-sort-header-container {
justify-content: inherit;
}
}
}
}
}
}

46
libs/ui/src/lib/account-balances/account-balances.component.ts

@ -0,0 +1,46 @@
import {
ChangeDetectionStrategy,
Component,
Input,
OnDestroy,
OnInit
} from '@angular/core';
import { DataService } from '@ghostfolio/client/services/data.service';
import { AccountBalance } from '@ghostfolio/common/interfaces';
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;
public balances: AccountBalance[];
public displayedColumns: string[] = ['date', 'value'];
private unsubscribeSubject = new Subject<void>();
public constructor(private dataService: DataService) {}
public fetchBalances() {
this.dataService
.fetchAccountBalances(this.accountId)
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ balances }) => {
console.log({ balances });
this.balances = balances;
});
}
public ngOnInit() {
this.fetchBalances();
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
}

44
libs/ui/src/lib/account-balances/account-balances.module.ts

@ -0,0 +1,44 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { GfSymbolIconModule } from '@ghostfolio/client/components/symbol-icon/symbol-icon.module';
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module';
import { GfActivityTypeModule } from '@ghostfolio/ui/activity-type';
import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info';
import { GfValueModule } from '@ghostfolio/ui/value';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { AccountBalancesComponent } from './account-balances.component';
@NgModule({
declarations: [AccountBalancesComponent],
exports: [AccountBalancesComponent],
imports: [
CommonModule,
GfActivitiesFilterModule,
GfActivityTypeModule,
GfNoTransactionsInfoModule,
GfSymbolIconModule,
GfSymbolModule,
GfValueModule,
MatButtonModule,
MatCheckboxModule,
MatMenuModule,
MatPaginatorModule,
MatSortModule,
MatTableModule,
MatTooltipModule,
NgxSkeletonLoaderModule,
RouterModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class GfAccountBalancesModule {}
Loading…
Cancel
Save