From 39a12ee05e5095c1376bb95f4970e308929fef82 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Fri, 6 Aug 2021 19:31:46 +0200 Subject: [PATCH] Extract allocations to separate page --- apps/client/src/app/app-routing.module.ts | 7 + apps/client/src/app/pages/home/home-page.html | 2 +- .../allocations-page-routing.module.ts | 15 ++ .../allocations/allocations-page.component.ts | 221 ++++++++++++++++++ .../allocations/allocations-page.html | 193 +++++++++++++++ .../allocations/allocations-page.module.ts | 27 +++ .../allocations/allocations-page.scss | 40 ++++ .../analysis/analysis-page.component.ts | 146 +----------- .../portfolio/analysis/analysis-page.html | 196 +--------------- .../analysis/analysis-page.module.ts | 10 +- .../portfolio/analysis/analysis-page.scss | 16 -- .../portfolio/portfolio-page.component.ts | 34 ++- .../app/pages/portfolio/portfolio-page.html | 15 +- ...-or-update-transaction-dialog.component.ts | 2 +- apps/client/src/app/pages/zen/zen-page.html | 2 +- 15 files changed, 552 insertions(+), 374 deletions(-) create mode 100644 apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts create mode 100644 apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts create mode 100644 apps/client/src/app/pages/portfolio/allocations/allocations-page.html create mode 100644 apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts create mode 100644 apps/client/src/app/pages/portfolio/allocations/allocations-page.scss diff --git a/apps/client/src/app/app-routing.module.ts b/apps/client/src/app/app-routing.module.ts index a741970bc..5ad41c077 100644 --- a/apps/client/src/app/app-routing.module.ts +++ b/apps/client/src/app/app-routing.module.ts @@ -59,6 +59,13 @@ const routes: Routes = [ (m) => m.PortfolioPageModule ) }, + { + path: 'portfolio/allocations', + loadChildren: () => + import('./pages/portfolio/allocations/allocations-page.module').then( + (m) => m.AllocationsPageModule + ) + }, { path: 'portfolio/analysis', loadChildren: () => diff --git a/apps/client/src/app/pages/home/home-page.html b/apps/client/src/app/pages/home/home-page.html index 861b5400a..be87fcd7a 100644 --- a/apps/client/src/app/pages/home/home-page.html +++ b/apps/client/src/app/pages/home/home-page.html @@ -79,7 +79,7 @@
-

Positions

+

Holdings

diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts new file mode 100644 index 000000000..8b2182fe4 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; + +import { AllocationsPageComponent } from './allocations-page.component'; + +const routes: Routes = [ + { path: '', component: AllocationsPageComponent, canActivate: [AuthGuard] } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AllocationsPageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts new file mode 100644 index 000000000..6aaf81148 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -0,0 +1,221 @@ +import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ToggleOption } from '@ghostfolio/client/components/toggle/interfaces/toggle-option.type'; +import { DataService } from '@ghostfolio/client/services/data.service'; +import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { UNKNOWN_KEY } from '@ghostfolio/common/config'; +import { PortfolioPosition, User } from '@ghostfolio/common/interfaces'; +import { DeviceDetectorService } from 'ngx-device-detector'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'gf-allocations-page', + templateUrl: './allocations-page.html', + styleUrls: ['./allocations-page.scss'] +}) +export class AllocationsPageComponent implements OnDestroy, OnInit { + public accounts: { + [symbol: string]: Pick & { value: number }; + }; + public continents: { + [code: string]: { name: string; value: number }; + }; + public countries: { + [code: string]: { name: string; value: number }; + }; + public deviceType: string; + public hasImpersonationId: boolean; + public period = 'current'; + public periodOptions: ToggleOption[] = [ + { label: 'Initial', value: 'original' }, + { label: 'Current', value: 'current' } + ]; + public portfolioPositions: { [symbol: string]: PortfolioPosition }; + public positions: { [symbol: string]: any }; + public positionsArray: PortfolioPosition[]; + public sectors: { + [name: string]: { name: string; value: number }; + }; + public user: User; + + private unsubscribeSubject = new Subject(); + + /** + * @constructor + */ + public constructor( + private changeDetectorRef: ChangeDetectorRef, + private dataService: DataService, + private deviceService: DeviceDetectorService, + private impersonationStorageService: ImpersonationStorageService, + private userService: UserService + ) {} + + /** + * Initializes the controller + */ + public ngOnInit() { + this.deviceType = this.deviceService.getDeviceInfo().deviceType; + + this.impersonationStorageService + .onChangeHasImpersonation() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((aId) => { + this.hasImpersonationId = !!aId; + }); + + this.dataService + .fetchPortfolioPositions({}) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((response = {}) => { + this.portfolioPositions = response; + this.initializeAnalysisData(this.portfolioPositions, this.period); + + this.changeDetectorRef.markForCheck(); + }); + + this.userService.stateChanged + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((state) => { + if (state?.user) { + this.user = state.user; + + this.changeDetectorRef.markForCheck(); + } + }); + } + + public initializeAnalysisData( + aPortfolioPositions: { + [symbol: string]: PortfolioPosition; + }, + aPeriod: string + ) { + this.accounts = {}; + this.continents = { + [UNKNOWN_KEY]: { + name: UNKNOWN_KEY, + value: 0 + } + }; + this.countries = { + [UNKNOWN_KEY]: { + name: UNKNOWN_KEY, + value: 0 + } + }; + this.positions = {}; + this.positionsArray = []; + this.sectors = { + [UNKNOWN_KEY]: { + name: UNKNOWN_KEY, + value: 0 + } + }; + + for (const [symbol, position] of Object.entries(aPortfolioPositions)) { + this.positions[symbol] = { + currency: position.currency, + exchange: position.exchange, + type: position.type, + value: + aPeriod === 'original' + ? position.allocationInvestment + : position.allocationCurrent + }; + this.positionsArray.push(position); + + for (const [account, { current, original }] of Object.entries( + position.accounts + )) { + if (this.accounts[account]?.value) { + this.accounts[account].value += + aPeriod === 'original' ? original : current; + } else { + this.accounts[account] = { + name: account, + value: aPeriod === 'original' ? original : current + }; + } + } + + if (position.countries.length > 0) { + for (const country of position.countries) { + const { code, continent, name, weight } = country; + + if (this.continents[continent]?.value) { + this.continents[continent].value += weight * position.value; + } else { + this.continents[continent] = { + name: continent, + value: + weight * + (aPeriod === 'original' + ? this.portfolioPositions[symbol].investment + : this.portfolioPositions[symbol].value) + }; + } + + if (this.countries[code]?.value) { + this.countries[code].value += weight * position.value; + } else { + this.countries[code] = { + name, + value: + weight * + (aPeriod === 'original' + ? this.portfolioPositions[symbol].investment + : this.portfolioPositions[symbol].value) + }; + } + } + } else { + this.continents[UNKNOWN_KEY].value += + aPeriod === 'original' + ? this.portfolioPositions[symbol].investment + : this.portfolioPositions[symbol].value; + + this.countries[UNKNOWN_KEY].value += + aPeriod === 'original' + ? this.portfolioPositions[symbol].investment + : this.portfolioPositions[symbol].value; + } + + if (position.sectors.length > 0) { + for (const sector of position.sectors) { + const { name, weight } = sector; + + if (this.sectors[name]?.value) { + this.sectors[name].value += weight * position.value; + } else { + this.sectors[name] = { + name, + value: + weight * + (aPeriod === 'original' + ? this.portfolioPositions[symbol].investment + : this.portfolioPositions[symbol].value) + }; + } + } + } else { + this.sectors[UNKNOWN_KEY].value += + aPeriod === 'original' + ? this.portfolioPositions[symbol].investment + : this.portfolioPositions[symbol].value; + } + } + } + + public onChangePeriod(aValue: string) { + this.period = aValue; + + this.initializeAnalysisData(this.portfolioPositions, this.period); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } +} diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html new file mode 100644 index 000000000..05f34d318 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html @@ -0,0 +1,193 @@ +
+
+
+

Allocations

+ +
+
+
+
+ + + By Type + + + + + + +
+
+ + + By Account + + + + + + +
+
+ + + By Currency + + + + + + +
+
+ + + By Exchange + + + + + + +
+
+ + + By Sector + + + + + + +
+
+ + + By Continent + + + + + + +
+
+ + + By Country + + + + + + +
+
+
+
+ + + Regions + + + + + + +
+
+
diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts new file mode 100644 index 000000000..d5d9fe0b5 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts @@ -0,0 +1,27 @@ +import { CommonModule } from '@angular/common'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { MatCardModule } from '@angular/material/card'; +import { PortfolioProportionChartModule } from '@ghostfolio/client/components/portfolio-proportion-chart/portfolio-proportion-chart.module'; +import { GfPositionsTableModule } from '@ghostfolio/client/components/positions-table/positions-table.module'; +import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; +import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; + +import { AllocationsPageRoutingModule } from './allocations-page-routing.module'; +import { AllocationsPageComponent } from './allocations-page.component'; + +@NgModule({ + declarations: [AllocationsPageComponent], + exports: [], + imports: [ + AllocationsPageRoutingModule, + CommonModule, + GfPositionsTableModule, + GfToggleModule, + GfWorldMapChartModule, + MatCardModule, + PortfolioProportionChartModule + ], + providers: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class AllocationsPageModule {} diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.scss b/apps/client/src/app/pages/portfolio/allocations/allocations-page.scss new file mode 100644 index 000000000..b41677eb6 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.scss @@ -0,0 +1,40 @@ +:host { + .proportion-charts { + .mat-card { + .mat-card-content { + padding: 1rem 2rem; + } + } + } + + .world-map-chart { + .mat-card { + .mat-card-content { + aspect-ratio: 16 / 9; + } + } + } + + .mat-card { + .mat-card-header { + ::ng-deep { + .mat-card-header-text { + flex: 1 1 auto; + } + } + + gf-toggle { + font-size: 90%; + } + } + + a { + color: rgba(var(--palette-primary-500), 1); + font-weight: 500; + + &:hover { + color: rgba(var(--palette-primary-300), 1); + } + } + } +} diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index 433bf63b1..187683930 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -3,12 +3,7 @@ import { ToggleOption } from '@ghostfolio/client/components/toggle/interfaces/to import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { UNKNOWN_KEY } from '@ghostfolio/common/config'; -import { - PortfolioItem, - PortfolioPosition, - User -} from '@ghostfolio/common/interfaces'; +import { PortfolioPosition, User } from '@ghostfolio/common/interfaces'; import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; @@ -39,7 +34,6 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { public investments: InvestmentItem[]; public portfolioPositions: { [symbol: string]: PortfolioPosition }; public positions: { [symbol: string]: any }; - public positionsArray: PortfolioPosition[]; public sectors: { [name: string]: { name: string; value: number }; }; @@ -80,16 +74,6 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); }); - this.dataService - .fetchPortfolioPositions({}) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((response = {}) => { - this.portfolioPositions = response; - this.initializeAnalysisData(this.portfolioPositions, this.period); - - this.changeDetectorRef.markForCheck(); - }); - this.userService.stateChanged .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((state) => { @@ -101,134 +85,6 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { }); } - public initializeAnalysisData( - aPortfolioPositions: { - [symbol: string]: PortfolioPosition; - }, - aPeriod: string - ) { - this.accounts = {}; - this.continents = { - [UNKNOWN_KEY]: { - name: UNKNOWN_KEY, - value: 0 - } - }; - this.countries = { - [UNKNOWN_KEY]: { - name: UNKNOWN_KEY, - value: 0 - } - }; - this.positions = {}; - this.positionsArray = []; - this.sectors = { - [UNKNOWN_KEY]: { - name: UNKNOWN_KEY, - value: 0 - } - }; - - for (const [symbol, position] of Object.entries(aPortfolioPositions)) { - this.positions[symbol] = { - currency: position.currency, - exchange: position.exchange, - type: position.type, - value: - aPeriod === 'original' - ? position.allocationInvestment - : position.allocationCurrent - }; - this.positionsArray.push(position); - - for (const [account, { current, original }] of Object.entries( - position.accounts - )) { - if (this.accounts[account]?.value) { - this.accounts[account].value += - aPeriod === 'original' ? original : current; - } else { - this.accounts[account] = { - name: account, - value: aPeriod === 'original' ? original : current - }; - } - } - - if (position.countries.length > 0) { - for (const country of position.countries) { - const { code, continent, name, weight } = country; - - if (this.continents[continent]?.value) { - this.continents[continent].value += weight * position.value; - } else { - this.continents[continent] = { - name: continent, - value: - weight * - (aPeriod === 'original' - ? this.portfolioPositions[symbol].investment - : this.portfolioPositions[symbol].value) - }; - } - - if (this.countries[code]?.value) { - this.countries[code].value += weight * position.value; - } else { - this.countries[code] = { - name, - value: - weight * - (aPeriod === 'original' - ? this.portfolioPositions[symbol].investment - : this.portfolioPositions[symbol].value) - }; - } - } - } else { - this.continents[UNKNOWN_KEY].value += - aPeriod === 'original' - ? this.portfolioPositions[symbol].investment - : this.portfolioPositions[symbol].value; - - this.countries[UNKNOWN_KEY].value += - aPeriod === 'original' - ? this.portfolioPositions[symbol].investment - : this.portfolioPositions[symbol].value; - } - - if (position.sectors.length > 0) { - for (const sector of position.sectors) { - const { name, weight } = sector; - - if (this.sectors[name]?.value) { - this.sectors[name].value += weight * position.value; - } else { - this.sectors[name] = { - name, - value: - weight * - (aPeriod === 'original' - ? this.portfolioPositions[symbol].investment - : this.portfolioPositions[symbol].value) - }; - } - } - } else { - this.sectors[UNKNOWN_KEY].value += - aPeriod === 'original' - ? this.portfolioPositions[symbol].investment - : this.portfolioPositions[symbol].value; - } - } - } - - public onChangePeriod(aValue: string) { - this.period = aValue; - - this.initializeAnalysisData(this.portfolioPositions, this.period); - } - public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html index 37137839b..0ed865686 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -1,199 +1,7 @@
-
-
-

Analysis

-
-

Positions

- -
-
-
-
-
- - - By Type - - - - - - -
-
- - - By Account - - - - - - -
-
- - - By Currency - - - - - - -
-
- - - By Exchange - - - - - - -
-
- - - By Sector - - - - - - -
-
- - - By Continent - - - - - - -
-
- - - By Country - - - - - - -
-
-
-
- - - Regions - - - - - - -
-
+

Analysis

diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts index d8974b3ca..53e9bb283 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts @@ -2,10 +2,6 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { MatCardModule } from '@angular/material/card'; import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module'; -import { PortfolioProportionChartModule } from '@ghostfolio/client/components/portfolio-proportion-chart/portfolio-proportion-chart.module'; -import { GfPositionsTableModule } from '@ghostfolio/client/components/positions-table/positions-table.module'; -import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; -import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; import { AnalysisPageRoutingModule } from './analysis-page-routing.module'; import { AnalysisPageComponent } from './analysis-page.component'; @@ -17,11 +13,7 @@ import { AnalysisPageComponent } from './analysis-page.component'; AnalysisPageRoutingModule, CommonModule, GfInvestmentChartModule, - GfPositionsTableModule, - GfToggleModule, - GfWorldMapChartModule, - MatCardModule, - PortfolioProportionChartModule + MatCardModule ], providers: [], schemas: [CUSTOM_ELEMENTS_SCHEMA] diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.scss b/apps/client/src/app/pages/portfolio/analysis/analysis-page.scss index 09e4ea30d..ab302d8e3 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.scss +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.scss @@ -11,22 +11,6 @@ } } - .proportion-charts { - .mat-card { - .mat-card-content { - padding: 1rem 2rem; - } - } - } - - .world-map-chart { - .mat-card { - .mat-card-content { - aspect-ratio: 16 / 9; - } - } - } - .mat-card { .mat-card-header { ::ng-deep { diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts index 84b44117a..668d3e351 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts +++ b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts @@ -1,18 +1,44 @@ -import { Component, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { User } from '@ghostfolio/common/interfaces'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'gf-portfolio-page', templateUrl: './portfolio-page.html', styleUrls: ['./portfolio-page.scss'] }) -export class PortfolioPageComponent implements OnInit { +export class PortfolioPageComponent implements OnDestroy, OnInit { + public user: User; + + private unsubscribeSubject = new Subject(); + /** * @constructor */ - public constructor() {} + public constructor( + private changeDetectorRef: ChangeDetectorRef, + private userService: UserService + ) {} /** * Initializes the controller */ - public ngOnInit() {} + public ngOnInit() { + this.userService.stateChanged + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((state) => { + if (state?.user) { + this.user = state.user; + + this.changeDetectorRef.markForCheck(); + } + }); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } } diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.html b/apps/client/src/app/pages/portfolio/portfolio-page.html index 1aca66097..1a2578be4 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.html +++ b/apps/client/src/app/pages/portfolio/portfolio-page.html @@ -17,7 +17,10 @@

-
+

Allocations

Check the allocations of your portfolio.

@@ -35,7 +38,10 @@
-
+

Analysis

Ghostfolio Analysis visualizes your portfolio.

@@ -51,7 +57,10 @@

-
+

X-ray

diff --git a/apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts b/apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts index a35e00152..42930fb27 100644 --- a/apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts @@ -9,6 +9,7 @@ import { FormControl, Validators } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface'; +import { DataService } from '@ghostfolio/client/services/data.service'; import { Currency } from '@prisma/client'; import { Observable, Subject } from 'rxjs'; import { @@ -19,7 +20,6 @@ import { takeUntil } from 'rxjs/operators'; -import { DataService } from '@ghostfolio/client/services/data.service'; import { CreateOrUpdateTransactionDialogParams } from './interfaces/interfaces'; @Component({ diff --git a/apps/client/src/app/pages/zen/zen-page.html b/apps/client/src/app/pages/zen/zen-page.html index a3f06be4e..200825c1a 100644 --- a/apps/client/src/app/pages/zen/zen-page.html +++ b/apps/client/src/app/pages/zen/zen-page.html @@ -60,7 +60,7 @@

-

Positions

+

Holdings