diff --git a/CHANGELOG.md b/CHANGELOG.md index f4720cc29..c65e878bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added the position detail dialog to the _Top 3_ and _Bottom 3_ performers of the analysis page + ### Changed - Increased the historical data chart of the _Fear & Greed Index_ (market mood) to 365 days +- Upgraded `color` from version `4.0.1` to `4.2.3` + +### Fixed + +- Fixed the rounding of the y-axis ticks in the benchmark comparator ## 1.219.0 - 2022-12-17 diff --git a/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts b/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts index f87e83a7a..8adffa005 100644 --- a/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts +++ b/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -187,7 +187,7 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy { position: 'right', ticks: { callback: (value: number) => { - return `${value} %`; + return `${value.toFixed(2)} %`; }, display: true, mirror: true, diff --git a/apps/client/src/app/components/position/position.component.html b/apps/client/src/app/components/position/position.component.html index cbd12e094..2f6b76bd9 100644 --- a/apps/client/src/app/components/position/position.component.html +++ b/apps/client/src/app/components/position/position.component.html @@ -3,12 +3,12 @@
{{ position?.name }}
- {{ position?.symbol | gfSymbol }} + {{ position?.symbol | gfSymbol }}
; }; - 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 ( diff --git a/package.json b/package.json index c3b1c1249..56df1f44a 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "cheerio": "1.0.0-rc.12", "class-transformer": "0.3.2", "class-validator": "0.13.1", - "color": "4.0.1", + "color": "4.2.3", "countries-list": "2.6.1", "countup.js": "2.0.7", "date-fns": "2.29.3", @@ -160,7 +160,7 @@ "@types/big.js": "6.1.6", "@types/bull": "3.15.9", "@types/cache-manager": "3.4.2", - "@types/color": "3.0.2", + "@types/color": "3.0.3", "@types/google-spreadsheet": "3.1.5", "@types/jest": "28.1.8", "@types/lodash": "4.14.174", diff --git a/yarn.lock b/yarn.lock index d9539a085..e49bf34d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4749,10 +4749,10 @@ resolved "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== -"@types/color@3.0.2": - version "3.0.2" - resolved "https://registry.npmjs.org/@types/color/-/color-3.0.2.tgz" - integrity sha512-INiJl6sfNn8iyC5paxVzqiVUEj2boIlFki02uRTAkKwAj++7aAF+ZfEv/XrIeBa0XI/fTZuDHW8rEEcEVnON+Q== +"@types/color@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/color/-/color-3.0.3.tgz#e6d8d72b7aaef4bb9fe80847c26c7c786191016d" + integrity sha512-X//qzJ3d3Zj82J9sC/C18ZY5f43utPbAJ6PhYt/M7uG6etcF6MRpKdN880KBy43B0BMzSfeT96MzrsNjFI3GbA== dependencies: "@types/color-convert" "*" @@ -7688,9 +7688,9 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.6.0: +color-string@^1.9.0: version "1.9.1" - resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== dependencies: color-name "^1.0.0" @@ -7701,13 +7701,13 @@ color-support@^1.1.2, color-support@^1.1.3: resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -color@4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/color/-/color-4.0.1.tgz" - integrity sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA== +color@4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== dependencies: color-convert "^2.0.1" - color-string "^1.6.0" + color-string "^1.9.0" colord@^2.9.1: version "2.9.2"