diff --git a/apps/client/src/app/components/markets/markets.component.ts b/apps/client/src/app/components/markets/markets.component.ts index 3c8fa50f95..3d09905bb0 100644 --- a/apps/client/src/app/components/markets/markets.component.ts +++ b/apps/client/src/app/components/markets/markets.component.ts @@ -3,8 +3,8 @@ import { DEFAULT_LOCALE } from '@ghostfolio/common/config'; import { resetHours } from '@ghostfolio/common/helper'; import { Benchmark, - HistoricalDataItem, InfoItem, + LineChartItem, MarketDataOfMarketsResponse, User } from '@ghostfolio/common/interfaces'; @@ -66,7 +66,7 @@ export class GfMarketsComponent implements OnInit { protected fearAndGreedIndexMode: FearAndGreedIndexMode = 'STOCKS'; protected hasPermissionToAccessFearAndGreedIndex: boolean; protected hasPermissionToReadMarketDataOfMarkets: boolean; - protected historicalDataItems: HistoricalDataItem[]; + protected historicalDataItems: LineChartItem[]; protected isLoadingFearAndGreedIndex = true; protected user: User; @@ -159,11 +159,16 @@ export class GfMarketsComponent implements OnInit { this.fearAndGreedIndexData[this.fearAndGreedIndexMode]?.marketPrice; this.historicalDataItems = [ - ...(this.fearAndGreedIndexData[this.fearAndGreedIndexMode] - ?.historicalData ?? []), + ...( + this.fearAndGreedIndexData[this.fearAndGreedIndexMode] + ?.historicalData ?? [] + ).map(({ date, value }) => ({ + date, + value: value ?? 0 + })), { date: resetHours(new Date()).toISOString(), - value: this.fearAndGreedIndex + value: this.fearAndGreedIndex ?? 0 } ]; } diff --git a/apps/client/src/app/components/markets/markets.html b/apps/client/src/app/components/markets/markets.html index 68b22d26f0..9131282ea0 100644 --- a/apps/client/src/app/components/markets/markets.html +++ b/apps/client/src/app/components/markets/markets.html @@ -29,7 +29,7 @@ [colorScheme]="user?.settings?.colorScheme" [historicalDataItems]="historicalDataItems" [isAnimated]="true" - [locale]="user?.settings?.locale || undefined" + [locale]="user?.settings?.locale ?? DEFAULT_LOCALE" [showXAxis]="true" [showYAxis]="true" [yMax]="100" diff --git a/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts index 90a0039cf0..0c66f5d4e4 100644 --- a/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts @@ -5,7 +5,7 @@ import { export interface RuleSettingsDialogParams { categoryName: string; - locale: string; + locale?: string; rule: PortfolioReportRule; settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment']; } diff --git a/apps/client/src/app/components/rule/rule.component.ts b/apps/client/src/app/components/rule/rule.component.ts index 7edc713cde..da6bf39ff4 100644 --- a/apps/client/src/app/components/rule/rule.component.ts +++ b/apps/client/src/app/components/rule/rule.component.ts @@ -8,11 +8,10 @@ import { import { ChangeDetectionStrategy, Component, + computed, DestroyRef, - EventEmitter, Input, - OnInit, - Output + output } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; @@ -41,17 +40,20 @@ import { GfRuleSettingsDialogComponent } from './rule-settings-dialog/rule-setti styleUrls: ['./rule.component.scss'], templateUrl: './rule.component.html' }) -export class GfRuleComponent implements OnInit { +export class GfRuleComponent { @Input() categoryName: string; @Input() hasPermissionToUpdateUserSettings: boolean; @Input() isLoading: boolean; - @Input() locale: string; + @Input() locale?: string; @Input() rule: PortfolioReportRule; @Input() settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment']; - @Output() ruleUpdated = new EventEmitter(); + public readonly ruleUpdated = output(); + + private readonly deviceType = computed(() => { + return this.deviceDetectorService.deviceInfo().deviceType; + }); - private deviceType: string; public constructor( private destroyRef: DestroyRef, private deviceDetectorService: DeviceDetectorService, @@ -67,11 +69,7 @@ export class GfRuleComponent implements OnInit { }); } - public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - } - - public onCustomizeRule(rule: PortfolioReportRule) { + protected onCustomizeRule(rule: PortfolioReportRule) { const dialogRef = this.dialog.open< GfRuleSettingsDialogComponent, RuleSettingsDialogParams @@ -82,7 +80,7 @@ export class GfRuleComponent implements OnInit { locale: this.locale, settings: this.settings }, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' + width: this.deviceType() === 'mobile' ? '100vw' : '50rem' }); dialogRef @@ -99,7 +97,7 @@ export class GfRuleComponent implements OnInit { }); } - public onUpdateRule(rule: PortfolioReportRule) { + protected onUpdateRule(rule: PortfolioReportRule) { const settings: UpdateUserSettingDto = { xRayRules: { [rule.key]: { isActive: !rule.isActive } diff --git a/apps/client/src/app/components/rules/rules.component.ts b/apps/client/src/app/components/rules/rules.component.ts index 22e1718f8c..97c21589e0 100644 --- a/apps/client/src/app/components/rules/rules.component.ts +++ b/apps/client/src/app/components/rules/rules.component.ts @@ -8,9 +8,8 @@ import { import { ChangeDetectionStrategy, Component, - EventEmitter, Input, - Output + output } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; @@ -26,13 +25,13 @@ export class GfRulesComponent { @Input() categoryName: string; @Input() hasPermissionToUpdateUserSettings: boolean; @Input() isLoading: boolean; - @Input() locale: string; + @Input() locale?: string; @Input() rules: PortfolioReportRule[]; - @Input() settings: XRayRulesSettings; + @Input() settings?: XRayRulesSettings; - @Output() rulesUpdated = new EventEmitter(); + public readonly rulesUpdated = output(); - public onRuleUpdated(event: UpdateUserSettingDto) { + protected onRuleUpdated(event: UpdateUserSettingDto) { this.rulesUpdated.emit(event); } } diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html index 559f639b15..911be41056 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -128,14 +128,12 @@ [hasPermissionToCreateActivity]="false" [hasPermissionToDeleteActivity]="false" [hasPermissionToExportActivities]="false" - [hasPermissionToFilter]="false" [hasPermissionToOpenDetails]="false" [locale]="data?.user?.settings?.locale" [pageIndex]="pageIndex" [pageSize]="pageSize" [showActions]="false" [showCheckbox]="true" - [showSymbolColumn]="false" [sortColumn]="sortColumn" [sortDirection]="sortDirection" [sortDisabled]="true" diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.html b/apps/client/src/app/pages/portfolio/fire/fire-page.html index 3f12ddc126..004bc1ed25 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.html +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -178,7 +178,7 @@ [isPercent]="true" [locale]="user?.settings?.locale" [precision]="2" - [value]="user?.settings?.annualInterestRate / 100" + [value]="(user?.settings?.annualInterestRate ?? 0) / 100" /> annual interest rate. diff --git a/apps/client/src/app/pages/pricing/pricing-page.html b/apps/client/src/app/pages/pricing/pricing-page.html index cf3bd2448a..8ab170b4b5 100644 --- a/apps/client/src/app/pages/pricing/pricing-page.html +++ b/apps/client/src/app/pages/pricing/pricing-page.html @@ -258,21 +258,23 @@

Fully managed Ghostfolio cloud offering.

-

- - @if (coupon) { - {{ baseCurrency }} {{ price }} {{ baseCurrency }} {{ - price - coupon - }} - } @else { - {{ baseCurrency }} {{ price }} - } -   - per year -

+ @if (price) { +

+ + @if (coupon) { + {{ baseCurrency }} {{ price }} {{ baseCurrency }} {{ + price - coupon + }} + } @else { + {{ baseCurrency }} {{ price }} + } +   + per year +

+ } @if ( hasPermissionToUpdateUserSettings && user?.subscription?.type === 'Basic'