Feature/add dialog for benchmarks in markets overview (#3493)
* Add benchmarks dialog in markets overview * Update changelog
This commit is contained in:
parent
79a7e12a9f
commit
519827045a
@ -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/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added a dialog for the benchmarks in the markets overview
|
||||||
|
|
||||||
## 2.89.0 - 2024-06-14
|
## 2.89.0 - 2024-06-14
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -25,6 +25,7 @@ import { AccessModule } from './access/access.module';
|
|||||||
import { AccountModule } from './account/account.module';
|
import { AccountModule } from './account/account.module';
|
||||||
import { AdminModule } from './admin/admin.module';
|
import { AdminModule } from './admin/admin.module';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
|
import { AssetModule } from './asset/asset.module';
|
||||||
import { AuthDeviceModule } from './auth-device/auth-device.module';
|
import { AuthDeviceModule } from './auth-device/auth-device.module';
|
||||||
import { AuthModule } from './auth/auth.module';
|
import { AuthModule } from './auth/auth.module';
|
||||||
import { BenchmarkModule } from './benchmark/benchmark.module';
|
import { BenchmarkModule } from './benchmark/benchmark.module';
|
||||||
@ -51,6 +52,7 @@ import { UserModule } from './user/user.module';
|
|||||||
AdminModule,
|
AdminModule,
|
||||||
AccessModule,
|
AccessModule,
|
||||||
AccountModule,
|
AccountModule,
|
||||||
|
AssetModule,
|
||||||
AuthDeviceModule,
|
AuthDeviceModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
BenchmarkModule,
|
BenchmarkModule,
|
||||||
|
29
apps/api/src/app/asset/asset.controller.ts
Normal file
29
apps/api/src/app/asset/asset.controller.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { AdminService } from '@ghostfolio/api/app/admin/admin.service';
|
||||||
|
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor';
|
||||||
|
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor';
|
||||||
|
import type { AdminMarketDataDetails } from '@ghostfolio/common/interfaces';
|
||||||
|
|
||||||
|
import { Controller, Get, Param, UseInterceptors } from '@nestjs/common';
|
||||||
|
import { DataSource } from '@prisma/client';
|
||||||
|
import { pick } from 'lodash';
|
||||||
|
|
||||||
|
@Controller('asset')
|
||||||
|
export class AssetController {
|
||||||
|
public constructor(private readonly adminService: AdminService) {}
|
||||||
|
|
||||||
|
@Get(':dataSource/:symbol')
|
||||||
|
@UseInterceptors(TransformDataSourceInRequestInterceptor)
|
||||||
|
@UseInterceptors(TransformDataSourceInResponseInterceptor)
|
||||||
|
public async getAsset(
|
||||||
|
@Param('dataSource') dataSource: DataSource,
|
||||||
|
@Param('symbol') symbol: string
|
||||||
|
): Promise<AdminMarketDataDetails> {
|
||||||
|
const { assetProfile, marketData } =
|
||||||
|
await this.adminService.getMarketDataBySymbol({ dataSource, symbol });
|
||||||
|
|
||||||
|
return {
|
||||||
|
marketData,
|
||||||
|
assetProfile: pick(assetProfile, ['dataSource', 'name', 'symbol'])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
17
apps/api/src/app/asset/asset.module.ts
Normal file
17
apps/api/src/app/asset/asset.module.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { AdminModule } from '@ghostfolio/api/app/admin/admin.module';
|
||||||
|
import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module';
|
||||||
|
import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module';
|
||||||
|
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { AssetController } from './asset.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [AssetController],
|
||||||
|
imports: [
|
||||||
|
AdminModule,
|
||||||
|
TransformDataSourceInRequestModule,
|
||||||
|
TransformDataSourceInResponseModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AssetModule {}
|
@ -105,7 +105,7 @@ export class BenchmarkController {
|
|||||||
@Get(':dataSource/:symbol/:startDateString')
|
@Get(':dataSource/:symbol/:startDateString')
|
||||||
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
|
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
|
||||||
@UseInterceptors(TransformDataSourceInRequestInterceptor)
|
@UseInterceptors(TransformDataSourceInRequestInterceptor)
|
||||||
public async getBenchmarkMarketDataBySymbol(
|
public async getBenchmarkMarketDataForUser(
|
||||||
@Param('dataSource') dataSource: DataSource,
|
@Param('dataSource') dataSource: DataSource,
|
||||||
@Param('startDateString') startDateString: string,
|
@Param('startDateString') startDateString: string,
|
||||||
@Param('symbol') symbol: string,
|
@Param('symbol') symbol: string,
|
||||||
@ -117,7 +117,7 @@ export class BenchmarkController {
|
|||||||
);
|
);
|
||||||
const userCurrency = this.request.user.Settings.settings.baseCurrency;
|
const userCurrency = this.request.user.Settings.settings.baseCurrency;
|
||||||
|
|
||||||
return this.benchmarkService.getMarketDataBySymbol({
|
return this.benchmarkService.getMarketDataForUser({
|
||||||
dataSource,
|
dataSource,
|
||||||
endDate,
|
endDate,
|
||||||
startDate,
|
startDate,
|
||||||
|
@ -153,6 +153,7 @@ export class BenchmarkService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
dataSource: benchmarkAssetProfiles[index].dataSource,
|
||||||
marketCondition: this.getMarketCondition(
|
marketCondition: this.getMarketCondition(
|
||||||
performancePercentFromAllTimeHigh
|
performancePercentFromAllTimeHigh
|
||||||
),
|
),
|
||||||
@ -163,6 +164,7 @@ export class BenchmarkService {
|
|||||||
performancePercent: performancePercentFromAllTimeHigh
|
performancePercent: performancePercentFromAllTimeHigh
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
symbol: benchmarkAssetProfiles[index].symbol,
|
||||||
trend50d: benchmarkTrends[index].trend50d,
|
trend50d: benchmarkTrends[index].trend50d,
|
||||||
trend200d: benchmarkTrends[index].trend200d
|
trend200d: benchmarkTrends[index].trend200d
|
||||||
};
|
};
|
||||||
@ -213,7 +215,7 @@ export class BenchmarkService {
|
|||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getMarketDataBySymbol({
|
public async getMarketDataForUser({
|
||||||
dataSource,
|
dataSource,
|
||||||
endDate = new Date(),
|
endDate = new Date(),
|
||||||
startDate,
|
startDate,
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
|
|
||||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ import { takeUntil } from 'rxjs/operators';
|
|||||||
})
|
})
|
||||||
export class HomeMarketComponent implements OnDestroy, OnInit {
|
export class HomeMarketComponent implements OnDestroy, OnInit {
|
||||||
public benchmarks: Benchmark[];
|
public benchmarks: Benchmark[];
|
||||||
|
public deviceType: string;
|
||||||
public fearAndGreedIndex: number;
|
public fearAndGreedIndex: number;
|
||||||
public fearLabel = $localize`Fear`;
|
public fearLabel = $localize`Fear`;
|
||||||
public greedLabel = $localize`Greed`;
|
public greedLabel = $localize`Greed`;
|
||||||
@ -36,8 +38,10 @@ export class HomeMarketComponent implements OnDestroy, OnInit {
|
|||||||
public constructor(
|
public constructor(
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private dataService: DataService,
|
private dataService: DataService,
|
||||||
|
private deviceService: DeviceDetectorService,
|
||||||
private userService: UserService
|
private userService: UserService
|
||||||
) {
|
) {
|
||||||
|
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
|
||||||
this.info = this.dataService.fetchInfo();
|
this.info = this.dataService.fetchInfo();
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
<div class="col-xs-12 col-md-8 offset-md-2">
|
<div class="col-xs-12 col-md-8 offset-md-2">
|
||||||
<gf-benchmark
|
<gf-benchmark
|
||||||
[benchmarks]="benchmarks"
|
[benchmarks]="benchmarks"
|
||||||
|
[deviceType]="deviceType"
|
||||||
[locale]="user?.settings?.locale || undefined"
|
[locale]="user?.settings?.locale || undefined"
|
||||||
[user]="user"
|
[user]="user"
|
||||||
/>
|
/>
|
||||||
|
@ -285,7 +285,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
this.isLoadingBenchmarkComparator = true;
|
this.isLoadingBenchmarkComparator = true;
|
||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchBenchmarkBySymbol({
|
.fetchBenchmarkForUser({
|
||||||
dataSource,
|
dataSource,
|
||||||
symbol,
|
symbol,
|
||||||
range: this.user?.settings?.dateRange,
|
range: this.user?.settings?.dateRange,
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
Access,
|
Access,
|
||||||
AccountBalancesResponse,
|
AccountBalancesResponse,
|
||||||
Accounts,
|
Accounts,
|
||||||
|
AdminMarketDataDetails,
|
||||||
BenchmarkMarketDataDetails,
|
BenchmarkMarketDataDetails,
|
||||||
BenchmarkResponse,
|
BenchmarkResponse,
|
||||||
Export,
|
Export,
|
||||||
@ -284,7 +285,21 @@ export class DataService {
|
|||||||
return this.http.get<Access[]>('/api/v1/access');
|
return this.http.get<Access[]>('/api/v1/access');
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchBenchmarkBySymbol({
|
public fetchAsset({
|
||||||
|
dataSource,
|
||||||
|
symbol
|
||||||
|
}: UniqueAsset): Observable<AdminMarketDataDetails> {
|
||||||
|
return this.http.get<any>(`/api/v1/asset/${dataSource}/${symbol}`).pipe(
|
||||||
|
map((data) => {
|
||||||
|
for (const item of data.marketData) {
|
||||||
|
item.date = parseISO(item.date);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public fetchBenchmarkForUser({
|
||||||
dataSource,
|
dataSource,
|
||||||
range,
|
range,
|
||||||
startDate,
|
startDate,
|
||||||
|
@ -3,6 +3,7 @@ import { BenchmarkTrend } from '@ghostfolio/common/types/';
|
|||||||
import { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface';
|
import { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface';
|
||||||
|
|
||||||
export interface Benchmark {
|
export interface Benchmark {
|
||||||
|
dataSource: EnhancedSymbolProfile['dataSource'];
|
||||||
marketCondition: 'ALL_TIME_HIGH' | 'BEAR_MARKET' | 'NEUTRAL_MARKET';
|
marketCondition: 'ALL_TIME_HIGH' | 'BEAR_MARKET' | 'NEUTRAL_MARKET';
|
||||||
name: EnhancedSymbolProfile['name'];
|
name: EnhancedSymbolProfile['name'];
|
||||||
performances: {
|
performances: {
|
||||||
@ -11,6 +12,7 @@ export interface Benchmark {
|
|||||||
performancePercent: number;
|
performancePercent: number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
symbol: EnhancedSymbolProfile['symbol'];
|
||||||
trend50d: BenchmarkTrend;
|
trend50d: BenchmarkTrend;
|
||||||
trend200d: BenchmarkTrend;
|
trend200d: BenchmarkTrend;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.mat-mdc-dialog-content {
|
||||||
|
max-height: unset;
|
||||||
|
|
||||||
|
gf-line-chart {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
margin: 0 -0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
|
||||||
|
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
|
||||||
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||||
|
import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
||||||
|
import {
|
||||||
|
AdminMarketDataDetails,
|
||||||
|
LineChartItem
|
||||||
|
} from '@ghostfolio/common/interfaces';
|
||||||
|
import { GfLineChartComponent } from '@ghostfolio/ui/line-chart';
|
||||||
|
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import {
|
||||||
|
CUSTOM_ELEMENTS_SCHEMA,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
Inject,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit
|
||||||
|
} from '@angular/core';
|
||||||
|
import {
|
||||||
|
MAT_DIALOG_DATA,
|
||||||
|
MatDialogModule,
|
||||||
|
MatDialogRef
|
||||||
|
} from '@angular/material/dialog';
|
||||||
|
import { format } from 'date-fns';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { BenchmarkDetailDialogParams } from './interfaces/interfaces';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
host: { class: 'd-flex flex-column h-100' },
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
GfDialogFooterModule,
|
||||||
|
GfDialogHeaderModule,
|
||||||
|
GfLineChartComponent,
|
||||||
|
MatDialogModule
|
||||||
|
],
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
selector: 'gf-benchmark-detail-dialog',
|
||||||
|
standalone: true,
|
||||||
|
styleUrls: ['./benchmark-detail-dialog.component.scss'],
|
||||||
|
templateUrl: 'benchmark-detail-dialog.html'
|
||||||
|
})
|
||||||
|
export class GfBenchmarkDetailDialogComponent implements OnDestroy, OnInit {
|
||||||
|
public assetProfile: AdminMarketDataDetails['assetProfile'];
|
||||||
|
public historicalDataItems: LineChartItem[];
|
||||||
|
|
||||||
|
private unsubscribeSubject = new Subject<void>();
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private dataService: DataService,
|
||||||
|
public dialogRef: MatDialogRef<GfBenchmarkDetailDialogComponent>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: BenchmarkDetailDialogParams
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public ngOnInit() {
|
||||||
|
this.dataService
|
||||||
|
.fetchAsset({
|
||||||
|
dataSource: this.data.dataSource,
|
||||||
|
symbol: this.data.symbol
|
||||||
|
})
|
||||||
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
|
.subscribe(({ assetProfile, marketData }) => {
|
||||||
|
this.assetProfile = assetProfile;
|
||||||
|
|
||||||
|
this.historicalDataItems = marketData.map(({ date, marketPrice }) => {
|
||||||
|
return { date: format(date, DATE_FORMAT), value: marketPrice };
|
||||||
|
});
|
||||||
|
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onClose() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnDestroy() {
|
||||||
|
this.unsubscribeSubject.next();
|
||||||
|
this.unsubscribeSubject.complete();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<gf-dialog-header
|
||||||
|
mat-dialog-title
|
||||||
|
position="center"
|
||||||
|
[deviceType]="data.deviceType"
|
||||||
|
[title]="assetProfile?.name ?? assetProfile?.symbol"
|
||||||
|
(closeButtonClicked)="onClose()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="flex-grow-1" mat-dialog-content>
|
||||||
|
<div class="container p-0">
|
||||||
|
<gf-line-chart
|
||||||
|
benchmarkLabel="Average Unit Price"
|
||||||
|
class="mb-4"
|
||||||
|
[colorScheme]="data.colorScheme"
|
||||||
|
[historicalDataItems]="historicalDataItems"
|
||||||
|
[isAnimated]="true"
|
||||||
|
[locale]="data.locale"
|
||||||
|
[showGradient]="true"
|
||||||
|
[showXAxis]="true"
|
||||||
|
[showYAxis]="true"
|
||||||
|
[symbol]="data.symbol"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<gf-dialog-footer
|
||||||
|
mat-dialog-actions
|
||||||
|
[deviceType]="data.deviceType"
|
||||||
|
(closeButtonClicked)="onClose()"
|
||||||
|
/>
|
@ -0,0 +1,11 @@
|
|||||||
|
import { ColorScheme } from '@ghostfolio/common/types';
|
||||||
|
|
||||||
|
import { DataSource } from '@prisma/client';
|
||||||
|
|
||||||
|
export interface BenchmarkDetailDialogParams {
|
||||||
|
colorScheme: ColorScheme;
|
||||||
|
dataSource: DataSource;
|
||||||
|
deviceType: string;
|
||||||
|
locale: string;
|
||||||
|
symbol: string;
|
||||||
|
}
|
@ -110,5 +110,15 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
|
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
|
||||||
<tr *matRowDef="let row; columns: displayedColumns" mat-row></tr>
|
<tr
|
||||||
|
*matRowDef="let row; columns: displayedColumns"
|
||||||
|
class="cursor-pointer"
|
||||||
|
mat-row
|
||||||
|
(click)="
|
||||||
|
onOpenBenchmarkDialog({
|
||||||
|
dataSource: row.dataSource,
|
||||||
|
symbol: row.symbol
|
||||||
|
})
|
||||||
|
"
|
||||||
|
></tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { getLocale, resolveMarketCondition } from '@ghostfolio/common/helper';
|
import { getLocale, resolveMarketCondition } from '@ghostfolio/common/helper';
|
||||||
import { Benchmark, User } from '@ghostfolio/common/interfaces';
|
import { Benchmark, UniqueAsset, User } from '@ghostfolio/common/interfaces';
|
||||||
import { translate } from '@ghostfolio/ui/i18n';
|
import { translate } from '@ghostfolio/ui/i18n';
|
||||||
|
import { GfTrendIndicatorComponent } from '@ghostfolio/ui/trend-indicator';
|
||||||
|
import { GfValueComponent } from '@ghostfolio/ui/value';
|
||||||
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import {
|
import {
|
||||||
@ -8,13 +10,17 @@ import {
|
|||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
Input,
|
Input,
|
||||||
OnChanges
|
OnChanges,
|
||||||
|
OnDestroy
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||||
|
import { Subject, takeUntil } from 'rxjs';
|
||||||
|
|
||||||
import { GfTrendIndicatorComponent } from '../trend-indicator';
|
import { GfBenchmarkDetailDialogComponent } from './benchmark-detail-dialog/benchmark-detail-dialog.component';
|
||||||
import { GfValueComponent } from '../value';
|
import { BenchmarkDetailDialogParams } from './benchmark-detail-dialog/interfaces/interfaces';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
@ -23,7 +29,8 @@ import { GfValueComponent } from '../value';
|
|||||||
GfTrendIndicatorComponent,
|
GfTrendIndicatorComponent,
|
||||||
GfValueComponent,
|
GfValueComponent,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
NgxSkeletonLoaderModule
|
NgxSkeletonLoaderModule,
|
||||||
|
RouterModule
|
||||||
],
|
],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
selector: 'gf-benchmark',
|
selector: 'gf-benchmark',
|
||||||
@ -31,8 +38,9 @@ import { GfValueComponent } from '../value';
|
|||||||
styleUrls: ['./benchmark.component.scss'],
|
styleUrls: ['./benchmark.component.scss'],
|
||||||
templateUrl: './benchmark.component.html'
|
templateUrl: './benchmark.component.html'
|
||||||
})
|
})
|
||||||
export class GfBenchmarkComponent implements OnChanges {
|
export class GfBenchmarkComponent implements OnChanges, OnDestroy {
|
||||||
@Input() benchmarks: Benchmark[];
|
@Input() benchmarks: Benchmark[];
|
||||||
|
@Input() deviceType: string;
|
||||||
@Input() locale = getLocale();
|
@Input() locale = getLocale();
|
||||||
@Input() user: User;
|
@Input() user: User;
|
||||||
|
|
||||||
@ -40,7 +48,28 @@ export class GfBenchmarkComponent implements OnChanges {
|
|||||||
public resolveMarketCondition = resolveMarketCondition;
|
public resolveMarketCondition = resolveMarketCondition;
|
||||||
public translate = translate;
|
public translate = translate;
|
||||||
|
|
||||||
public constructor() {}
|
private unsubscribeSubject = new Subject<void>();
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
this.route.queryParams
|
||||||
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
|
.subscribe((params) => {
|
||||||
|
if (
|
||||||
|
params['benchmarkDetailDialog'] &&
|
||||||
|
params['dataSource'] &&
|
||||||
|
params['symbol']
|
||||||
|
) {
|
||||||
|
this.openBenchmarkDetailDialog({
|
||||||
|
dataSource: params['dataSource'],
|
||||||
|
symbol: params['symbol']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public ngOnChanges() {
|
public ngOnChanges() {
|
||||||
if (this.user?.settings?.isExperimentalFeatures) {
|
if (this.user?.settings?.isExperimentalFeatures) {
|
||||||
@ -54,4 +83,36 @@ export class GfBenchmarkComponent implements OnChanges {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onOpenBenchmarkDialog({ dataSource, symbol }: UniqueAsset) {
|
||||||
|
this.router.navigate([], {
|
||||||
|
queryParams: { dataSource, symbol, benchmarkDetailDialog: true }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnDestroy() {
|
||||||
|
this.unsubscribeSubject.next();
|
||||||
|
this.unsubscribeSubject.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private openBenchmarkDetailDialog({ dataSource, symbol }: UniqueAsset) {
|
||||||
|
const dialogRef = this.dialog.open(GfBenchmarkDetailDialogComponent, {
|
||||||
|
data: <BenchmarkDetailDialogParams>{
|
||||||
|
dataSource,
|
||||||
|
symbol,
|
||||||
|
colorScheme: this.user?.settings?.colorScheme,
|
||||||
|
deviceType: this.deviceType,
|
||||||
|
locale: this.locale
|
||||||
|
},
|
||||||
|
height: this.deviceType === 'mobile' ? '97.5vh' : undefined,
|
||||||
|
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef
|
||||||
|
.afterClosed()
|
||||||
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
|
.subscribe(() => {
|
||||||
|
this.router.navigate(['.'], { relativeTo: this.route });
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user