|
|
@ -1,15 +1,17 @@ |
|
|
import { GfFearAndGreedIndexComponent } from '@ghostfolio/client/components/fear-and-greed-index/fear-and-greed-index.component'; |
|
|
|
|
|
import { UserService } from '@ghostfolio/client/services/user/user.service'; |
|
|
import { UserService } from '@ghostfolio/client/services/user/user.service'; |
|
|
import { resetHours } from '@ghostfolio/common/helper'; |
|
|
import { resetHours } from '@ghostfolio/common/helper'; |
|
|
import { |
|
|
import { |
|
|
Benchmark, |
|
|
Benchmark, |
|
|
HistoricalDataItem, |
|
|
HistoricalDataItem, |
|
|
|
|
|
InfoItem, |
|
|
MarketDataOfMarketsResponse, |
|
|
MarketDataOfMarketsResponse, |
|
|
ToggleOption, |
|
|
ToggleOption, |
|
|
User |
|
|
User |
|
|
} from '@ghostfolio/common/interfaces'; |
|
|
} from '@ghostfolio/common/interfaces'; |
|
|
|
|
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; |
|
|
import { FearAndGreedIndexMode } from '@ghostfolio/common/types'; |
|
|
import { FearAndGreedIndexMode } from '@ghostfolio/common/types'; |
|
|
import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; |
|
|
import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; |
|
|
|
|
|
import { GfFearAndGreedIndexComponent } from '@ghostfolio/ui/fear-and-greed-index'; |
|
|
import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; |
|
|
import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; |
|
|
import { DataService } from '@ghostfolio/ui/services'; |
|
|
import { DataService } from '@ghostfolio/ui/services'; |
|
|
import { GfToggleComponent } from '@ghostfolio/ui/toggle'; |
|
|
import { GfToggleComponent } from '@ghostfolio/ui/toggle'; |
|
|
@ -18,9 +20,12 @@ import { |
|
|
ChangeDetectionStrategy, |
|
|
ChangeDetectionStrategy, |
|
|
ChangeDetectorRef, |
|
|
ChangeDetectorRef, |
|
|
Component, |
|
|
Component, |
|
|
|
|
|
computed, |
|
|
CUSTOM_ELEMENTS_SCHEMA, |
|
|
CUSTOM_ELEMENTS_SCHEMA, |
|
|
DestroyRef, |
|
|
DestroyRef, |
|
|
OnInit |
|
|
inject, |
|
|
|
|
|
OnInit, |
|
|
|
|
|
signal |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
import { DeviceDetectorService } from 'ngx-device-detector'; |
|
|
import { DeviceDetectorService } from 'ngx-device-detector'; |
|
|
@ -39,29 +44,50 @@ import { DeviceDetectorService } from 'ngx-device-detector'; |
|
|
templateUrl: './markets.html' |
|
|
templateUrl: './markets.html' |
|
|
}) |
|
|
}) |
|
|
export class GfMarketsComponent implements OnInit { |
|
|
export class GfMarketsComponent implements OnInit { |
|
|
public benchmarks: Benchmark[]; |
|
|
protected readonly benchmarks = signal<Benchmark[]>([]); |
|
|
public deviceType: string; |
|
|
|
|
|
public fearAndGreedIndex: number; |
|
|
protected readonly deviceType = computed( |
|
|
public fearAndGreedIndexData: MarketDataOfMarketsResponse['fearAndGreedIndex']; |
|
|
() => this.deviceDetectorService.deviceInfo().deviceType |
|
|
public fearLabel = $localize`Fear`; |
|
|
); |
|
|
public greedLabel = $localize`Greed`; |
|
|
|
|
|
public historicalDataItems: HistoricalDataItem[]; |
|
|
protected readonly fearAndGreedIndexModeOptions: ToggleOption[] = [ |
|
|
public fearAndGreedIndexMode: FearAndGreedIndexMode = 'STOCKS'; |
|
|
|
|
|
public fearAndGreedIndexModeOptions: ToggleOption[] = [ |
|
|
|
|
|
{ label: $localize`Stocks`, value: 'STOCKS' }, |
|
|
{ label: $localize`Stocks`, value: 'STOCKS' }, |
|
|
{ label: $localize`Cryptocurrencies`, value: 'CRYPTOCURRENCIES' } |
|
|
{ label: $localize`Cryptocurrencies`, value: 'CRYPTOCURRENCIES' } |
|
|
]; |
|
|
]; |
|
|
public readonly numberOfDays = 365; |
|
|
|
|
|
public user: User; |
|
|
protected readonly fearLabel = $localize`Fear`; |
|
|
|
|
|
protected readonly greedLabel = $localize`Greed`; |
|
|
public constructor( |
|
|
protected readonly numberOfDays = 365; |
|
|
private changeDetectorRef: ChangeDetectorRef, |
|
|
|
|
|
private dataService: DataService, |
|
|
protected fearAndGreedIndex: number | undefined; |
|
|
private destroyRef: DestroyRef, |
|
|
protected fearAndGreedIndexMode: FearAndGreedIndexMode = 'STOCKS'; |
|
|
private deviceDetectorService: DeviceDetectorService, |
|
|
protected hasPermissionToAccessFearAndGreedIndex: boolean; |
|
|
private userService: UserService |
|
|
protected hasPermissionToReadMarketDataOfMarkets: boolean; |
|
|
) { |
|
|
protected historicalDataItems: HistoricalDataItem[]; |
|
|
this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; |
|
|
protected isLoadingFearAndGreedIndex = true; |
|
|
|
|
|
protected user: User; |
|
|
|
|
|
|
|
|
|
|
|
private fearAndGreedIndexData: MarketDataOfMarketsResponse['fearAndGreedIndex']; |
|
|
|
|
|
|
|
|
|
|
|
private readonly info: InfoItem; |
|
|
|
|
|
|
|
|
|
|
|
private readonly changeDetectorRef = inject(ChangeDetectorRef); |
|
|
|
|
|
private readonly dataService = inject(DataService); |
|
|
|
|
|
private readonly destroyRef = inject(DestroyRef); |
|
|
|
|
|
private readonly deviceDetectorService = inject(DeviceDetectorService); |
|
|
|
|
|
private readonly userService = inject(UserService); |
|
|
|
|
|
|
|
|
|
|
|
public constructor() { |
|
|
|
|
|
this.info = this.dataService.fetchInfo(); |
|
|
|
|
|
|
|
|
|
|
|
this.hasPermissionToAccessFearAndGreedIndex = hasPermission( |
|
|
|
|
|
this.info?.globalPermissions, |
|
|
|
|
|
permissions.enableFearAndGreedIndex |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (this.hasPermissionToAccessFearAndGreedIndex) { |
|
|
|
|
|
this.fearAndGreedIndex = this.info.fearAndGreedStocksMarketPrice; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this.userService.stateChanged |
|
|
this.userService.stateChanged |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
@ -69,6 +95,20 @@ export class GfMarketsComponent implements OnInit { |
|
|
if (state?.user) { |
|
|
if (state?.user) { |
|
|
this.user = state.user; |
|
|
this.user = state.user; |
|
|
|
|
|
|
|
|
|
|
|
this.hasPermissionToReadMarketDataOfMarkets = hasPermission( |
|
|
|
|
|
this.user.permissions, |
|
|
|
|
|
permissions.readMarketDataOfMarkets |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
this.hasPermissionToReadMarketDataOfMarkets && |
|
|
|
|
|
!this.fearAndGreedIndexData |
|
|
|
|
|
) { |
|
|
|
|
|
this.fetchMarketDataOfMarkets(); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.isLoadingFearAndGreedIndex = false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this.changeDetectorRef.markForCheck(); |
|
|
this.changeDetectorRef.markForCheck(); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
@ -76,27 +116,37 @@ export class GfMarketsComponent implements OnInit { |
|
|
|
|
|
|
|
|
public ngOnInit() { |
|
|
public ngOnInit() { |
|
|
this.dataService |
|
|
this.dataService |
|
|
.fetchMarketDataOfMarkets({ includeHistoricalData: this.numberOfDays }) |
|
|
.fetchBenchmarks() |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe(({ fearAndGreedIndex }) => { |
|
|
.subscribe(({ benchmarks }) => { |
|
|
this.fearAndGreedIndexData = fearAndGreedIndex; |
|
|
this.benchmarks.set(benchmarks); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this.initialize(); |
|
|
protected onChangeFearAndGreedIndexMode( |
|
|
|
|
|
aFearAndGreedIndexMode: FearAndGreedIndexMode |
|
|
|
|
|
) { |
|
|
|
|
|
this.fearAndGreedIndexMode = aFearAndGreedIndexMode; |
|
|
|
|
|
|
|
|
this.changeDetectorRef.markForCheck(); |
|
|
this.initializeFearAndGreedIndex(); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fetchMarketDataOfMarkets() { |
|
|
this.dataService |
|
|
this.dataService |
|
|
.fetchBenchmarks() |
|
|
.fetchMarketDataOfMarkets({ includeHistoricalData: this.numberOfDays }) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe(({ benchmarks }) => { |
|
|
.subscribe(({ fearAndGreedIndex }) => { |
|
|
this.benchmarks = benchmarks; |
|
|
this.fearAndGreedIndexData = fearAndGreedIndex; |
|
|
|
|
|
|
|
|
|
|
|
this.initializeFearAndGreedIndex(); |
|
|
|
|
|
|
|
|
|
|
|
this.isLoadingFearAndGreedIndex = false; |
|
|
|
|
|
|
|
|
this.changeDetectorRef.markForCheck(); |
|
|
this.changeDetectorRef.markForCheck(); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public initialize() { |
|
|
private initializeFearAndGreedIndex() { |
|
|
this.fearAndGreedIndex = |
|
|
this.fearAndGreedIndex = |
|
|
this.fearAndGreedIndexData[this.fearAndGreedIndexMode]?.marketPrice; |
|
|
this.fearAndGreedIndexData[this.fearAndGreedIndexMode]?.marketPrice; |
|
|
|
|
|
|
|
|
@ -109,12 +159,4 @@ export class GfMarketsComponent implements OnInit { |
|
|
} |
|
|
} |
|
|
]; |
|
|
]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onChangeFearAndGreedIndexMode( |
|
|
|
|
|
aFearAndGreedIndexMode: FearAndGreedIndexMode |
|
|
|
|
|
) { |
|
|
|
|
|
this.fearAndGreedIndexMode = aFearAndGreedIndexMode; |
|
|
|
|
|
|
|
|
|
|
|
this.initialize(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|