From e8a4a53c9fa7bbf10b5da1c988742ad0c5b25ed6 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 19 Dec 2022 09:36:34 +0100 Subject: [PATCH] Feature/support position detail dialog in top performers of analysis page (#1522) * Add support for position detail dialog * Update changelog --- CHANGELOG.md | 6 ++ .../allocations/allocations-page.component.ts | 5 +- .../analysis/analysis-page.component.ts | 66 +++++++++++++++- .../portfolio/analysis/analysis-page.html | 79 +++++++++++-------- .../holdings/holdings-page.component.ts | 5 +- 5 files changed, 123 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0865cc183..86b64aec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 the position detail dialog to the _Top 3_ and _Bottom 3_ performers of the analysis page + ## 1.219.0 - 2022-12-17 ### Added 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 640ba2869..ea0f65ac0 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 @@ -22,7 +22,7 @@ import { Market, ToggleOption } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { Account, AssetClass, DataSource } from '@prisma/client'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject, Subscription } from 'rxjs'; +import { Subject } from 'rxjs'; import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators'; @Component({ @@ -71,7 +71,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { | 'value' >; }; - public routeQueryParams: Subscription; public sectors: { [name: string]: { name: string; value: number }; }; @@ -98,7 +97,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { private router: Router, private userService: UserService ) { - this.routeQueryParams = route.queryParams + route.queryParams .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((params) => { if (params['accountId'] && params['accountDetailDialog']) { 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 1cfc598d3..2f7e3ff58 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 @@ -1,4 +1,8 @@ import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { PositionDetailDialogParams } from '@ghostfolio/client/components/position/position-detail-dialog/interfaces/interfaces'; +import { PositionDetailDialog } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.component'; import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; @@ -9,8 +13,9 @@ import { User } from '@ghostfolio/common/interfaces'; import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { DateRange, GroupBy, ToggleOption } from '@ghostfolio/common/types'; -import { SymbolProfile } from '@prisma/client'; +import { DataSource, SymbolProfile } from '@prisma/client'; import { differenceInDays } from 'date-fns'; import { sortBy } from 'lodash'; import { DeviceDetectorService } from 'ngx-device-detector'; @@ -54,12 +59,30 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private dialog: MatDialog, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, + private route: ActivatedRoute, + private router: Router, private userService: UserService ) { const { benchmarks } = this.dataService.fetchInfo(); this.benchmarks = benchmarks; + + route.queryParams + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((params) => { + if ( + params['dataSource'] && + params['positionDetailDialog'] && + params['symbol'] + ) { + this.openPositionDialog({ + dataSource: params['dataSource'], + symbol: params['symbol'] + }); + } + }); } public ngOnInit() { @@ -128,6 +151,47 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { this.unsubscribeSubject.complete(); } + private openPositionDialog({ + dataSource, + symbol + }: { + dataSource: DataSource; + symbol: string; + }) { + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((user) => { + this.user = user; + + const dialogRef = this.dialog.open(PositionDetailDialog, { + autoFocus: false, + data: { + dataSource, + symbol, + baseCurrency: this.user?.settings?.baseCurrency, + colorScheme: this.user?.settings?.colorScheme, + deviceType: this.deviceType, + hasImpersonationId: this.hasImpersonationId, + hasPermissionToReportDataGlitch: hasPermission( + this.user?.permissions, + permissions.reportDataGlitch + ), + locale: this.user?.settings?.locale + }, + height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); + + dialogRef + .afterClosed() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.router.navigate(['.'], { relativeTo: this.route }); + }); + }); + } + private update() { this.isLoadingBenchmarkComparator = true; this.isLoadingInvestmentChart = true; 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 053ba835a..2f54f96d3 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -35,20 +35,30 @@ > -
-
- {{ i + 1 }}. {{ position.name }} -
-
- -
+
-
-
- {{ i + 1 }}. {{ position.name }} -
-
- -
+
(); @@ -51,7 +50,7 @@ export class HoldingsPageComponent implements OnDestroy, OnInit { private router: Router, private userService: UserService ) { - this.routeQueryParams = route.queryParams + route.queryParams .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((params) => { if (