From 2400a9b703835379f793eb222f8a93ba5d4acb4c Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sun, 24 Apr 2022 08:24:34 +0200 Subject: [PATCH] Setup allocations page and endpoint --- .../src/app/portfolio/portfolio.controller.ts | 6 ++- .../src/app/portfolio/portfolio.service.ts | 13 +++++-- .../allocations/allocations-page.component.ts | 38 +++++++++++++------ .../allocations/allocations-page.html | 5 +++ .../allocations/allocations-page.module.ts | 2 + apps/client/src/app/services/data.service.ts | 10 ++++- 6 files changed, 55 insertions(+), 19 deletions(-) diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index ad06dbb52..b62ea98db 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -105,7 +105,8 @@ export class PortfolioController { @UseInterceptors(TransformDataSourceInResponseInterceptor) public async getDetails( @Headers('impersonation-id') impersonationId: string, - @Query('range') range + @Query('range') range, + @Query('tags') tags?: string ): Promise { let hasError = false; @@ -113,7 +114,8 @@ export class PortfolioController { await this.portfolioService.getDetails( impersonationId, this.request.user.id, - range + range, + tags?.split(',') ); if (hasErrors || hasNotDefinedValuesInObject(holdings)) { diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index a7dc8adf7..86fc1398f 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -303,7 +303,8 @@ export class PortfolioService { public async getDetails( aImpersonationId: string, aUserId: string, - aDateRange: DateRange = 'max' + aDateRange: DateRange = 'max', + tags?: string[] ): Promise { const userId = await this.getUserId(aImpersonationId, aUserId); const user = await this.userService.user({ id: userId }); @@ -318,6 +319,7 @@ export class PortfolioService { const { orders, portfolioOrders, transactionPoints } = await this.getTransactionPoints({ + tags, userId }); @@ -441,8 +443,10 @@ export class PortfolioService { value: totalValue }); - for (const symbol of Object.keys(cashPositions)) { - holdings[symbol] = cashPositions[symbol]; + if (tags === undefined) { + for (const symbol of Object.keys(cashPositions)) { + holdings[symbol] = cashPositions[symbol]; + } } const accounts = await this.getValueOfAccounts( @@ -1178,9 +1182,11 @@ export class PortfolioService { private async getTransactionPoints({ includeDrafts = false, + tags, userId }: { includeDrafts?: boolean; + tags?: string[]; userId: string; }): Promise<{ transactionPoints: TransactionPoint[]; @@ -1191,6 +1197,7 @@ export class PortfolioService { const orders = await this.orderService.getOrders({ includeDrafts, + tags, userCurrency, userId, types: ['BUY', 'SELL'] 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 index da5e07025..954fd4abd 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -48,6 +48,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { { label: 'Initial', value: 'original' }, { label: 'Current', value: 'current' } ]; + public placeholder = ''; public portfolioDetails: PortfolioDetails; public positions: { [symbol: string]: Pick< @@ -73,6 +74,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { value: number; }; }; + public tags = ['high-risk', 'pension']; public user: User; @@ -120,17 +122,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { this.hasImpersonationId = !!aId; }); - this.dataService - .fetchPortfolioDetails({}) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((portfolioDetails) => { - this.portfolioDetails = portfolioDetails; - - this.initializeAnalysisData(this.period); - - this.changeDetectorRef.markForCheck(); - }); - this.userService.stateChanged .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((state) => { @@ -142,7 +133,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { }); } - public initializeAnalysisData(aPeriod: string) { + public initialize() { this.accounts = {}; this.continents = { [UNKNOWN_KEY]: { @@ -185,6 +176,10 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { value: 0 } }; + } + + public initializeAnalysisData(aPeriod: string) { + this.initialize(); for (const [id, { current, name, original }] of Object.entries( this.portfolioDetails.accounts @@ -342,6 +337,25 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { } } + public onUpdateFilters(tags: string[] = []) { + this.update(tags); + } + + public update(tags?: string[]) { + this.initialize(); + + this.dataService + .fetchPortfolioDetails({ tags }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((portfolioDetails) => { + this.portfolioDetails = portfolioDetails; + + this.initializeAnalysisData(this.period); + + this.changeDetectorRef.markForCheck(); + }); + } + 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 index dac241b1d..aaf4ee655 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html @@ -2,6 +2,11 @@

Allocations

+
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 index 62dd05e4e..fc8791775 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts @@ -4,6 +4,7 @@ import { MatCardModule } from '@angular/material/card'; 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 { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module'; import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module'; import { GfValueModule } from '@ghostfolio/ui/value'; @@ -16,6 +17,7 @@ import { AllocationsPageComponent } from './allocations-page.component'; imports: [ AllocationsPageRoutingModule, CommonModule, + GfActivitiesFilterModule, GfPortfolioProportionChartModule, GfPositionsTableModule, GfToggleModule, diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index b51a00ce8..c59982824 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -182,9 +182,15 @@ export class DataService { ); } - public fetchPortfolioDetails(aParams: { [param: string]: any }) { + public fetchPortfolioDetails({ tags }: { tags?: string[] }) { + let params = new HttpParams(); + + if (tags?.length > 0) { + params = params.append('tags', tags.join(',')); + } + return this.http.get('/api/v1/portfolio/details', { - params: aParams + params }); }